Opening documents

Declare supported files in Day.toml:

[[file_types]]
extensions = ["epub"]
mime_types = ["application/epub+zip"]
apple_uti = "org.idpf.epub-container"

Day generates the native file association. This enables Open With and, on macOS, dropping a file onto the app’s Finder or Dock icon. Use exact MIME types and extensions without leading dots. Use the established Apple UTI when one exists.

For a format the app itself defines, say so, and say how the app uses it:

[[file_types]]
extensions = ["daynote"]
mime_types = ["application/x-daynote"]
name = "file-type-daynote"   # a Fluent message: the type's name in Finder and Explorer
role = "editor"               # viewer (default) | editor | none
rank = "owner"                # alternate (default) | default | owner | none
exported = true               # the app defines this type

An exported type becomes the app’s own on Apple platforms and gets a MIME type on Linux. With rank = "owner", the Windows installer also makes the app the default for those files.

Register a receiver in the app root:

day::on_open_files(move |files| {
    day::task(async move {
        for locator in files {
            let file = FileUrl::new(locator);
            match file.read_limited(64 * 1024 * 1024).await {
                Ok(bytes) => import_book(bytes).await,
                Err(error) => show_import_error(error),
            }
        }
    });
});

import_book and show_import_error are application functions. Validate the contents and use localized error messages. The callback runs on the UI thread; native file reads run on a worker. Requests received before the root mounts are queued. Registration ends when its reactive scope is disposed.

Use the same import function for the native file picker. A reusable command can expose it in the desktop File menu with Shortcut::new("o"), and in a mobile toolbar. See Reusable commands.

The app decides what an open request does. A reader can import into its private library, deduplicate by content hash, and call day::open_window with a stable book key on desktop. On mobile, it can navigate to the reader in the current window. File registration does not create windows or overwrite documents automatically.

Platform differences

  • Apple bundles carry document types with their role and rank, and exported or imported UTIs. AppKit receives open-document events; UIKit receives app/scene URL contexts and imports copies. Native reads retain security-scoped access for the duration of the read.
  • Android and HarmonyOS copy granted provider files asynchronously into temporary app cache. Persist accepted content in your own storage. Staging is limited to 512 MiB.
  • Linux packages include MIME associations and file arguments in their desktop entry, and a shared-mime-info package for the app’s own types.
  • Windows MSIX and NSIS packages register Open With handlers. Windows GTK/Qt development builds emit an opt-in register.reg; their distribution packaging still requires a custom installer. The NSIS installer makes the app the default only for rank = "owner" types, and restores the previous default on uninstall.
  • macOS GTK/Qt builds with declared file types produce development app bundles for Finder/Dock testing. These reference local resources and installed toolkit libraries; they are not redistributable packages.
  • Installed web apps use the browser’s File Handling API when available. Unsupported browsers and ordinary tabs still use the file picker.

Some desktop activations start a new process rather than contacting an existing one. The editor role tells the system the app edits these files; the app still receives a copy to read, and persistent mobile provider grants are not part of this API.

The document reference covers the full platform mapping, cache lifetime, command-line delivery, manifest fields, testing, and native API references.