Skip to content

Commit 410a0c1

Browse files
committed
📝 Backup readme from v0.8.8
1 parent bb14620 commit 410a0c1

File tree

1 file changed

+333
-0
lines changed

1 file changed

+333
-0
lines changed

documentation-v0.8.8.md

Lines changed: 333 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,333 @@
1+
<div align="center">
2+
<img src="https://github.com/vinceglb/FileKit/assets/24540801/5ad7fc2d-04fd-4ba7-b5de-b4a7ada753c9" alt="FileKit for Kotlin Multiplatform and Compose Multiplatform" />
3+
4+
<br>
5+
6+
<h1>FileKit</h1>
7+
<p>Files, Medias, Folder Picker and File saver library for Kotlin Multiplatform and Compose Multiplatform</p>
8+
9+
<div>
10+
<img src="https://img.shields.io/maven-central/v/io.github.vinceglb/filekit-core" alt="FileKit Kotlin Maven Version" />
11+
<img src="https://img.shields.io/badge/Platform-Android-brightgreen.svg?logo=android" alt="Badge Android" />
12+
<img src="https://img.shields.io/badge/Platform-iOS%20%2F%20macOS-lightgrey.svg?logo=apple" alt="Badge iOS" />
13+
<img src="https://img.shields.io/badge/Platform-JVM-8A2BE2.svg?logo=openjdk" alt="Badge JVM" />
14+
<img src="https://img.shields.io/badge/Platform-WASM%20%2F%20JS-yellow.svg?logo=javascript" alt="Badge JS" />
15+
</div>
16+
17+
<br>
18+
</div>
19+
20+
FileKit is a library that allows you to pick and save files in a simple way. On each platform, it uses the native file picker API to provide a consistent experience.
21+
22+
## 🚀 Quick Start
23+
24+
Pick a file, a directory or save a file in common code:
25+
26+
```kotlin
27+
// Pick a file
28+
val file = FileKit.pickFile()
29+
30+
// Pick a directory
31+
val directory = FileKit.pickDirectory()
32+
33+
// Save a file
34+
val file = FileKit.saveFile(
35+
extension = "txt",
36+
bytes = "Hello, World!".encodeToByteArray()
37+
)
38+
```
39+
40+
Get file information in common code:
41+
42+
```kotlin
43+
val filePath = file?.path
44+
val fileName = file?.name
45+
val bytes = file?.readBytes()
46+
```
47+
48+
Compose Multiplatform integration made simple:
49+
50+
```kotlin
51+
// Pick files from Compose
52+
val launcher = rememberFilePickerLauncher(mode = PickerMode.Multiple()) { files ->
53+
// Handle picked files
54+
}
55+
56+
// Use the pickerLauncher
57+
Button(onClick = { launcher.launch() }) {
58+
Text("Pick files")
59+
}
60+
```
61+
62+
![FileKit Preview](https://github.com/vinceglb/FileKit/assets/24540801/e8a7bc49-41cc-4632-84c4-1013fd23dd76)
63+
64+
## 📦 Installation
65+
66+
```gradle
67+
repositories {
68+
mavenCentral()
69+
}
70+
71+
dependencies {
72+
// Enables FileKit without Compose dependencies
73+
implementation("io.github.vinceglb:filekit-core:0.8.8")
74+
75+
// Enables FileKit with Composable utilities
76+
implementation("io.github.vinceglb:filekit-compose:0.8.8")
77+
}
78+
```
79+
80+
If using JVM target and Linux distribution, you need to add the following module:
81+
82+
```gradle
83+
compose.desktop {
84+
application {
85+
nativeDistributions {
86+
linux {
87+
modules("jdk.security.auth")
88+
}
89+
}
90+
}
91+
}
92+
```
93+
94+
## ⚡ Initialization
95+
96+
Using **FileKit Core methods on Android** requires an initialization:
97+
- `FileKit.pickFile()`
98+
- `FileKit.pickDirectory()`
99+
- `FileKit.saveFile()`
100+
101+
In this case, only if using Android, you need to initialize FileKit in your `ComponentActivity`:
102+
103+
```kotlin
104+
// MainActivity.kt
105+
class MainActivity : ComponentActivity() {
106+
override fun onCreate() {
107+
super.onCreate()
108+
FileKit.init(this)
109+
}
110+
}
111+
```
112+
113+
In all other cases, you can use FileKit without initialization.
114+
115+
## 📄 File Picker
116+
117+
### Picker types
118+
119+
You can pick different types of files with `PickerType`:
120+
- `Image`: Pick an image file.
121+
- `Video`: Pick a video file.
122+
- `ImageAndVideo`: Pick an image or a video file.
123+
- `File`: Pick any file. It is the default type. It's possible to specify a list of extensions.
124+
125+
```kotlin
126+
val imageType = PickerType.Image
127+
val videoType = PickerType.Video
128+
val imageAndVideoType = PickerType.ImageAndVideo
129+
val fileType = PickerType.File(extensions = listOf("pdf", "docx"))
130+
```
131+
132+
### Picker modes
133+
134+
You can pick files in different modes with `PickerMode`. The mode will change the output type. `Single` is the default mode.
135+
136+
```kotlin
137+
val singleMode = PickerMode.Single
138+
val multipleMode = PickerMode.Multiple()
139+
```
140+
141+
#### Max items
142+
143+
On Android and iOS, when using `PickerType` `Image`, `Video` or `ImageAndVideo`, we can use `PickerMode.Multiple(maxItems = X)` to limit the number of picked files. The value must be between 1 and 50. Default value is `null` (no limit).
144+
145+
### Launch the picker
146+
147+
You can launch the picker with `FileKit.pickFile` or `rememberFilePickerLauncher`:
148+
149+
```kotlin
150+
// FileKit Core
151+
val file = FileKit.pickFile(
152+
type = PickerType.Image,
153+
mode = PickerMode.Single,
154+
title = "Pick an image",
155+
initialDirectory = "/custom/initial/path"
156+
)
157+
158+
// FileKit Compose
159+
val launcher = rememberFilePickerLauncher(
160+
type = PickerType.ImageAndVideo,
161+
mode = PickerMode.Multiple(),
162+
title = "Pick a media",
163+
initialDirectory = "/custom/initial/path"
164+
) { files ->
165+
// Handle the picked files
166+
}
167+
launcher.launch()
168+
```
169+
170+
## 📁 Directory Picker
171+
172+
You can pick a directory with `FileKit.pickDirectory` or `rememberDirectoryPickerLauncher`:
173+
174+
```kotlin
175+
// FileKit Core
176+
val directory = FileKit.pickDirectory(
177+
title = "Pick a directory",
178+
initialDirectory = "/custom/initial/path"
179+
)
180+
181+
// FileKit Compose
182+
val launcher = rememberDirectoryPickerLauncher(
183+
title = "Pick a directory",
184+
initialDirectory = "/custom/initial/path"
185+
) { directory ->
186+
// Handle the picked directory
187+
}
188+
launcher.launch()
189+
```
190+
191+
The directory picker is available on all platforms, expect for WASM / JS. To check if the directory picker is available from the common code, you can use `FileKit.isDirectoryPickerSupported()`.
192+
193+
```kotlin
194+
val directoryModeSupported = FileKit.isDirectoryPickerSupported()
195+
```
196+
197+
## 💾 Save File Picker
198+
199+
You can save a file with `FileKit.saveFile` or `rememberFileSaverLauncher`:
200+
201+
```kotlin
202+
// FileKit Core
203+
val file = FileKit.saveFile(
204+
baseName = "myTextFile",
205+
extension = "txt",
206+
initialDirectory = "/custom/initial/path",
207+
bytes = "Hello, World!".encodeToByteArray()
208+
)
209+
210+
// FileKit Compose
211+
val launcher = rememberFileSaverLauncher() { file ->
212+
// Handle the saved file
213+
}
214+
launcher.launch(
215+
baseName = "myTextFile",
216+
extension = "txt",
217+
initialDirectory = "/custom/initial/path",
218+
bytes = "Hello, World!".encodeToByteArray()
219+
)
220+
```
221+
222+
### Optional bytes argument
223+
224+
Bytes argument is optional. If you don't provide it, the file will be empty. This feature is available on Android, iOS, macOS and JVM. It is not available on WASM / JS.
225+
226+
To check if it's possible to save a file without bytes from the common code, you can use:
227+
228+
```kotlin
229+
val isSupported: Boolean = FileKit.isSaveFileWithoutBytesSupported()
230+
```
231+
232+
## 🧑‍💻 PlatformFile and PlatformDirectory
233+
234+
The `PlatformFile` and `PlatformDirectory` classes are wrappers around the platform file system. It allows you to get the file name, path and read the file content in common code.
235+
236+
```kotlin
237+
val platformFile: PlatformFile = ...
238+
239+
val filePath: String? = platformFile.path
240+
val fileName: String = platformFile.name // Base name with extension
241+
val baseName: String = platformFile.baseName
242+
val extension: String = platformFile.extension
243+
val size: Long = platformFile.getSize()
244+
val bytes: ByteArray = platformFile.readBytes() // suspend function
245+
246+
val platformDirectory: PlatformDirectory = ...
247+
val directoryPath: String? = platformDirectory.path
248+
```
249+
250+
On each platform, you can get the original platform file:
251+
252+
```kotlin
253+
// Android
254+
val uri: Uri = platformFile.uri
255+
val uri: Uri = platformDirectory.uri
256+
257+
// iOS / macOS
258+
val nsUrl: NSURL = platformFile.nsUrl
259+
val nsUrl: NSURL = platformDirectory.nsUrl
260+
261+
// JVM
262+
val file: java.io.File = platformFile.file
263+
val file: java.io.File = platformDirectory.file
264+
265+
// WASM / JS
266+
val file: org.w3c.files.File = platformFile.file
267+
val file: org.w3c.files.File = // PlatformDirectory not supported on WASM / JS
268+
```
269+
270+
## 🕺 Going further with files
271+
272+
[KMPFile](https://github.com/zacharee/KMPFile) is a library built by [@zacharee](https://github.com/zacharee) that provides a common API to work with files in Kotlin Multiplatform.
273+
274+
It mimics the Java File API available on Android, JVM, iOS and macOS. It's a great companion to FileKit to work with files in a consistent way across all platforms.
275+
276+
Also, KMPFile provides built-in support for FileKit's `PlatformFile` and `PlatformDirectory` classes thanks to [a dedicated library](https://github.com/zacharee/KMPFile?tab=readme-ov-file#picking-files).
277+
278+
Get started with KMPFile by visiting this repository: https://github.com/zacharee/KMPFile
279+
280+
## 🤏 Proguard & obfuscation
281+
282+
If using Proguard or obfuscation on JVM, you need to add the following rules:
283+
284+
```proguard
285+
-keep class com.sun.jna.** { *; }
286+
-keep class * implements com.sun.jna.** { *; }
287+
```
288+
289+
## 🌱 Sample projects
290+
291+
You can find 2 sample projects in the `samples` directory:
292+
- `sample-core`: A Kotlin Multiplatform project using FileKit in a shared viewModel targeting Android, JVM, WASM, JS, iOS Swift, macOS Swift and iOS Compose.
293+
- `sample-compose`: A Compose Multiplatform project using FileKit in a Composable targeting Android, iOS, JVM, WASM,
294+
295+
## ✨ Behind the scene
296+
297+
FileKit uses the native file picker API on each platform:
298+
299+
- On Android, it uses `PickVisualMedia`, `OpenDocument` and `OpenDocumentTree` contracts.
300+
- On iOS, it uses both `UIDocumentPickerViewController` and `PHPickerViewController` APIs.
301+
- On macOS, it uses the `NSOpenPanel` API.
302+
- On JVM, it uses JNA to access the file system on Windows and macOS and XDG Desktop Portal on Linux.
303+
- On WASM / JS, it uses the `input` element with the `file` type.
304+
305+
Also, FileKit uses the bear minimum of dependencies to be as lightweight as possible.
306+
307+
FileKit Core uses the following libraries:
308+
- [KotlinX Coroutines](https://github.com/Kotlin/kotlinx.coroutines)
309+
- Only Android: [AndroidX Activity KTX](https://developer.android.com/jetpack/androidx/releases/activity)
310+
- Only JVM: [Java Native Access - JNA](https://github.com/java-native-access/jna/tree/master)
311+
- Only JVM: [XDG Desktop Portal](https://github.com/hypfvieh/dbus-java)
312+
313+
FileKit Compose uses the following libraries:
314+
- [Jetbrains Compose Runtime](https://github.com/JetBrains/compose-multiplatform)
315+
- Only Android: [AndroidX Activity Compose](https://developer.android.com/jetpack/androidx/releases/activity)
316+
317+
## 😎 Credits
318+
319+
FileKit is inspired by the following libraries:
320+
321+
- [compose-multiplatform-file-picker](https://github.com/Wavesonics/compose-multiplatform-file-picker)
322+
- [peekaboo](https://github.com/onseok/peekaboo)
323+
- [Calf](https://github.com/MohamedRejeb/Calf)
324+
- [jnafilechooser](https://github.com/steos/jnafilechooser)
325+
- [swing-jnafilechooser](https://github.com/DJ-Raven/swing-jnafilechooser)
326+
- [nativefiledialog](https://github.com/mlabbe/nativefiledialog)
327+
- [IFileDialogImp](https://github.com/dbwiddis/IFileDialogImp)
328+
- [IntelliJ Community Foundation](https://github.com/JetBrains/intellij-community/blob/master/platform/util/ui/src/com/intellij/ui/mac/foundation/Foundation.java)
329+
- [file_picker (flutter)](https://pub.dev/packages/file_picker)
330+
331+
---
332+
333+
Made with ❤️ by Vince

0 commit comments

Comments
 (0)