Files and media picker
PAM Native imports selected content into the application sandbox and returns a
FileReference. The absolute device path stays private; use uri() as the
opaque source for Image and MediaPlayer.
Pick one file
Section titled “Pick one file”use Pam\Native\FileReference;use Pam\Native\MediaPickerType;use Pam\Native\System\Files;
Files::pick( MediaPickerType::Image, function (FileReference $file): void { $this->previewSource = $file->uri(); },);The available filters are sequential integer enum cases:
| Case | Value | Native filter |
|---|---|---|
MediaPickerType::Image |
1 |
Images |
MediaPickerType::Video |
2 |
Videos |
MediaPickerType::Audio |
3 |
Audio |
MediaPickerType::Any |
4 |
Any openable document |
MediaPickerType::Media |
5 |
Images and videos |
Use Media for social galleries. Unlike Any, it prevents PDFs, XML files,
archives, and unrelated documents from appearing alongside photos and videos.
The filter is implemented with Android MIME filters and iOS UTType filters.
Pick multiple media items
Section titled “Pick multiple media items”Files::pickMany( MediaPickerType::Media, function (array $files): void { $this->media = array_map( static fn (FileReference $file): array => [ 'mimeType' => $file->mimeType, 'name' => $file->name, 'size' => $file->size, 'uri' => $file->uri(), ], $files, ); }, limit: 10,);The native picker owns selection UI and enforces a bounded limit between 1 and 50. PAM copies each accepted item once into its sandbox, preserving the provider’s display name and MIME type.
Build a custom Android gallery
Section titled “Build a custom Android gallery”PAM Native 0.5.57 adds a direct, typed Android gallery API. It queries
MediaStore on a dedicated worker, returns bounded pages of metadata, and gives
the renderer stable content:// thumbnail sources. No thumbnail bytes cross
the PHP bridge and no source file is copied while the user scrolls.
use Pam\Native\FileReference;use Pam\Native\MediaAsset;use Pam\Native\MediaAssetPage;use Pam\Native\MediaPickerType;use Pam\Native\PermissionKind;use Pam\Native\System\Files;use Pam\Native\System\MediaLibrary;use Pam\Native\System\Permissions;
Permissions::requestKind(PermissionKind::Photos, function ($decision): void { if (!$decision->granted()) { return; }
MediaLibrary::assets( MediaPickerType::Media, function (MediaAssetPage $page): void { $this->assets = array_map( static fn (MediaAsset $asset): array => [ 'id' => $asset->id, 'source' => $asset->uri, 'width' => $asset->width, 'height' => $asset->height, 'durationMs' => $asset->durationMs, 'video' => $asset->video(), ], $page->items, ); $this->nextOffset = $page->nextOffset; $this->hasMore = $page->hasMore; }, limit: 80, offset: $this->nextOffset, albumId: $this->albumId ?: null, );});
MediaLibrary::albums( MediaPickerType::Media, fn (array $albums) => $this->albums = $albums,);Android 13 distinguishes image and video access. Android 14 may grant only the
photos selected by the user; PAM reports this as
PermissionStatus::Limited, and PermissionDecision::granted() accepts it.
The query naturally returns only assets visible to the application.
Keep gallery cells pointed at $asset->uri. When the user confirms an item,
materialize only that asset into app-owned storage:
public function select(MediaAsset $asset): void{ Files::importUri( $asset->uri, function (FileReference $file): void { $this->editorSource = $file->uri(); $this->uploadPath = $file->path; }, );}MediaLibrary is Android-only in 0.5.57. Keep Files::pick() or
Files::pickMany() visible as the portable fallback and as an escape hatch
when gallery access is denied or blocked.
Display imported content
Section titled “Display imported content”<Image :source="$selectedImage" resizeMode="cover" fadeDuration="0"/>
<MediaPlayer :source="$selectedVideo" controls="true" cache="none"/>Keep the returned URI in component state while the editor is mounted. This avoids reopening the provider, copying the file again, or decoding a new source on every render.
Draw over images without pointer traffic
Section titled “Draw over images without pointer traffic”DrawingCanvas places a native freehand surface over an aspect-fit image.
Brush and eraser movement stays on the platform UI thread, including coalesced
touch samples; PHP receives one compact drawing document only after a stroke
finishes.
<DrawingCanvas class="editor-canvas" :source="$selectedImage" :value="$drawing" brushColor="#FFFFFFFF" brushWidth="6" drawingMode="brush" :undoRequest="$undoRequest" :clearRequest="$clearRequest" on:change="updateDrawing"/>Use drawingMode="eraser" to remove previously drawn pixels. Increment
undoRequest or clearRequest to issue those commands; they are request
tokens, not booleans. The versioned JSON value is bounded to 256 strokes and
2,048 points per stroke. Coordinates and brush widths are normalized to the
actual displayed image content, so letterboxing, device density, and export
dimensions do not shift the drawing.
Edit and resize images off the UI thread
Section titled “Edit and resize images off the UI thread”ImageEditor::render() performs crop, rotation, horizontal flip, filters,
color adjustments, text/sticker composition, resize, and JPEG encoding on a
dedicated native worker. The callback returns another sandboxed
FileReference.
use Pam\Native\FileReference;use Pam\Native\ImageCropRatio;use Pam\Native\ImageFilterType;use Pam\Native\System\ImageEditor;
ImageEditor::render( source: $selected, cropRatio: ImageCropRatio::Square, filter: ImageFilterType::Original, quarterTurns: 0, flipHorizontal: false, overlayText: '', callback: function (?FileReference $image, string $error): void { if ($image instanceof FileReference) { $this->uploadPath = $image->path; } }, maxWidth: 1080, maxHeight: 1080, outputQuality: 92, drawing: $drawing,);maxWidth and maxHeight default to 0, which preserves the cropped
dimensions. Positive values bound the output without upscaling it.
outputQuality is clamped to the inclusive range 1–100 and defaults to 94.
On Android, PAM reads source bounds and selects a decode sample before bitmap
allocation, then applies one final filtered resize. Large camera photos
therefore avoid a needless full-resolution decode when the destination is a
thumbnail, avatar, or bounded attachment.
When drawing is provided, PAM flattens the native drawing document into the
source before rotation, crop, filters, overlays, resize, and encoding. Android
and iOS do this work outside the UI thread.