C+
Packages · View as Markdown

filepicker

The system's own file chooser.

[dependencies]
filepicker = "*"

Use cpc pm add . filepicker to write the platform-specific dependency closure.

import "filepicker/filepicker" as fp;

fn picked(p: fp::Pick, ctx: *u8) {
    if !p.chose() { return; }        // they cancelled — an answer, not an error
    open_it(p.path);
}

let _o: fp::Outcome = fp::open(picked, types: "png,jpg");

Asynchronous everywhere

Every platform hands the screen to another process and answers later, so there is no blocking form — not even on macOS, where runModal exists. A modal run loop inside a facet app is a reentrancy problem, not a convenience.

The return value is whether the picker opened. The choice arrives on the handler.

A cancel is an answer

The handler runs either way, with an empty path. chose() is the check.

path is not always a path

On Android it is a content:// URI from the Storage Access Framework — opaque, provider-owned, and not something fs::open_read can take. Read it with ContentResolver.openInputStream. Handing back an invented filesystem path would be a lie.

Coverage

macOS iOS Android Linux Windows
open ✅ XDG portal GetOpenFileNameW
save ❌ no such picker CREATE_DOCUMENT ✅ XDG portal GetSaveFileNameW
types filter ✅ extensions ❌ ignored ✅ one MIME family ✅ extension globs not wired yet — every file shown
returned value path path content:// URI decoded file path path

Tests

cd vendor/filepicker && cpc test

A visible picker cannot be automated in the unit suite; pure mapping and validation paths are tested.