Pickers
filmstrip-io-filekit-compose wraps FileKit’s dialogs so they hand back filmstrip’s own types. It’s a separate artifact,
so it isn’t in the filmstrip bundle. For the non-Compose FileKit bindings, see
Sources and sinks.
Pick a clip
Section titled “Pick a clip”rememberMediaPickerLauncher opens a video picker by default. onResult gets a PickedMedia, or null when the dialog was
dismissed. A dismissal isn’t an error, and onError only hears about a pick that started and can’t finish.
var source by remember { mutableStateOf<MediaSource?>(null) }val picker = rememberMediaPickerLauncher { picked -> source = picked?.source }
BasicText("Pick a clip", Modifier.clickable { picker.launch() })PickedMedia has the source to hand to a composition and the file the dialog returned. Reading a file’s name goes
through the content resolver on Android, so read it once in the callback and hold on to it.
In a browser the source is an object URL that lives until the page unloads. MediaSource.release frees it earlier, once
nothing reads the source any more.
Pick an image
Section titled “Pick an image”rememberImagePickerLauncher works the same way and gives you a PickedImage, whose source is an ImageSource for an
overlay or a still.
var watermark by remember { mutableStateOf<ImageSource?>(null) }val picker = rememberImagePickerLauncher { picked -> watermark = picked?.source }
BasicText("Pick a watermark", Modifier.clickable { picker.launch() })Choose where to save
Section titled “Choose where to save”rememberExportSaverLauncher asks for a destination and hands it back as a MediaSink.
var destination by remember { mutableStateOf<MediaSink?>(null) }val saver = rememberExportSaverLauncher { sink -> destination = sink }
BasicText("Export", Modifier.clickable { saver.launch(suggestedName = "holiday", defaultExtension = "mp4") })Android, Apple and the JVM open the platform’s save dialog. A browser opens nothing and reports a sink right away, named
after the launch arguments, which is the name the export downloads under. Leave the extension off suggestedName, since a
name already ending in it gets it a second time.
rememberShareLauncher opens the platform’s share sheet. It’s null on the JVM and in a browser, where FileKit has no share
sheet, so hide the control there.
val share = rememberShareLauncher()
if (share != null) { BasicText("Share", Modifier.clickable { share.launch(output) })}launch takes the sink an export reported. MediaSink.Temporary is a request and not a location, so it throws
IllegalStateException. Read the resolved path off ExportStatus.Success.output instead.