ReviewOS

craft-native/craft

No way to pick a general file: the document picker exists but is nailed to video

#387
Closed glennmichael123 opened this 8 days ago ·
8 days ago

An application can let someone attach a photo or a video, and cannot let them attach anything else. There is no way to choose a PDF, a CSV, a .fit or .gpx export, or a document, because no action opens a document picker for general content.

Asking for this from HQ.training, where direct messages should carry files as well as photos.

What is already here

Almost all of it, which is why this is a widening rather than a new capability.

CraftNativeFiles.swift:305 already runs a full document-picker flow inside pickVideo when source: "files":

var types: [UTType] = [.movie]
if let webm = UTType(filenameExtension: "webm") { types.append(webm) }
let picker = UIDocumentPickerViewController(forOpeningContentTypes: types, asCopy: true)

with a UIDocumentPickerDelegate, startAccessingSecurityScopedResource() handling, and a copy into app-owned storage. describe() (CraftNativeFiles.swift:70) already returns exactly the shape an attachment needs:

["path": url.path, "name": url.lastPathComponent, "type": type, "size": size]

Everything downstream of the pick works for any file already:

  • http.upload sends a real multipart/form-data body over uploadTask(with:fromFile:)
  • Files.download fetches one back
  • Share.share accepts files: [{ path, name }], so a recipient can open what they received
  • Files.write / Files.remove manage the local copy

What blocks it

Two places, both narrow.

The picker is nailed to video. types above is [.movie] plus webm, so the sheet will not offer anything else.

The copy enforces a video allowlist. CraftNativeFiles.swift:333:

let types = ["mp4": "video/mp4", "m4v": "video/x-m4v", "mov": "video/quicktime", "webm": "video/webm"]

and line 335 rejects everything else with INVALID_VIDEO — "Choose an MP4, MOV or WebM video."

Nothing is registered. The dispatcher in CraftNativeActions.swift has pickImage (243), pickVideo (250), download (256), write (259), remove (269). There is no pickFile. pickFile / pickDocument appear nowhere in the TypeScript surface either — CraftFileSystemAPI exposes only readFile, writeFile, readDir, mkdir, remove, exists.

Suggested shape

  • ("Files", "pickFile") in the dispatcher.
  • A copyFile sibling to copyVideo: same security-scoped copy and size limit, but the caller states what it will accept rather than the framework assuming video.
  • pickFile(options?: { contentTypes?: string[], maxSelections?: number, maxBytes?: number }): Promise<FileInfo[]> on CraftMobileAPI, returning describe()'s { path, name, type, size }.
  • contentTypes as UTI strings or filename extensions, defaulting to "anything", so an application decides its own policy. An application that wants only PDFs should be able to say so in the sheet rather than filtering after the fact, which is both worse UX and a weaker check.

One thing that is not required

In-app preview. There is no QLPreviewController anywhere, so a received PDF cannot be previewed inside the app — but Share.share already covers opening it elsewhere, so this is a separate nice-to-have and not part of this issue.

Note for applications

enableShare and enableCamera both default to false. An application that adds file attachments and forgets enableShare will find Share.share answering CAPABILITY_DISABLED, so a recipient can download a file and then have no way to open it. Worth a line in the docs beside whatever gate pickFile ends up behind.

8 days ago

Implemented and shipped on main in a3d4b5b, d7a68cd, and f6f1818. Added the iOS Files.pickFile capability with MIME/UTI/extension filters, multi-selection, size limits, owned-file copying, and typed TypeScript/browser fallback APIs. Added generated-source, TypeScript, iOS simulator unit, and UI verification. Native simulator: 225 unit tests + 5 UI tests passed; SDK: 753 passed.

Sign in to comment on this issue.