Lynx/Modules/Camera/API reference
@sigx/lynx-camera · Stable

API reference#

Exports of @sigx/lynx-camera — one runtime object plus the capture option, result, and cancel types.

The complete public surface is a single Camera const plus the type-only exports:

TypeScript
import { Camera } from '@sigx/lynx-camera';
import type {
  CameraOptions,
  PhotoResult,
  CameraVideoOptions,
  VideoResult,
  CameraCancelled,
  PermissionResponse,
} from '@sigx/lynx-camera';

PermissionResponse is re-exported from @sigx/lynx-core. Every method below works on both iOS and Android.

Object#

Camera#

The single namespace object exposing all camera APIs. It is backed by the native Camera module through @sigx/lynx-core.

TypeScript
const Camera: {
  takePicture(options?: CameraOptions): Promise<PhotoResult | CameraCancelled>;
  recordVideo(options?: CameraVideoOptions): Promise<VideoResult | CameraCancelled>;
  requestPermission(): Promise<PermissionResponse>;
  getPermissionStatus(): Promise<PermissionResponse>;
  isAvailable(): boolean;
};

See the methods below for each member.

Methods#

The three-outcome contract#

Both takePicture and recordVideo follow the same contract, so you narrow them the same way:

  • Success — resolves with a result that always carries a uri (PhotoResult / VideoResult).
  • Cancel — resolves with CameraCancelled ({ cancelled: true }, no uri) when the user dismisses the camera. The Android { error: "cancelled" } sentinel is normalized into this shape.
  • Failurethrows on a real error (permission denied, no camera, native bridge missing, …).

So callers narrow on result.uri for the success path and try / catch failures:

TypeScript
try {
  const photo = await Camera.takePicture({ quality: 0.8 });
  if (photo.uri) {
    // captured — load it
  } else {
    // user cancelled
  }
} catch (err) {
  // permission denied / no camera / …
}

Camera.takePicture#

Opens the system camera in photo mode.

TypeScript
takePicture(options?: CameraOptions): Promise<PhotoResult | CameraCancelled>

Platform notes: most option fields are iOS-only — iOS honors facing and JPEG quality; Android's ACTION_IMAGE_CAPTURE intent ignores capture options (the user can still switch cameras in its UI). The returned uri is normalized to a scheme: file:// on iOS (a temp filesystem path) and content:// on Android (a JPEG in the app cache directory, via FileProvider). On Android, takePicture now auto-requests the CAMERA runtime permission before launching the intent (see requestPermission).

Camera.recordVideo#

Opens the system camera in video mode and records a clip. The returned uri is loadable directly by @sigx/lynx-video's VideoPlayer.

TypeScript
recordVideo(options?: CameraVideoOptions): Promise<VideoResult | CameraCancelled>

Platform notes: iOS uses UIImagePickerController movie mode, honoring maxDurationMs (videoMaximumDuration) and facing (cameraDevice); Android launches an ACTION_VIDEO_CAPTURE intent, which exposes no duration cap and ignores capture options. The uri is file:// on iOS and content:// on Android. On Android, recordVideo auto-requests the CAMERA permission (and microphone too, when the app declares RECORD_AUDIO, e.g. via @sigx/lynx-audio) before launching. A single in-camera photo/video toggle is iOS-only at the system level — offer a "photo or video" choice in your own UI and call the matching method.

Camera.requestPermission#

Requests camera permission, showing the OS dialog if needed.

TypeScript
requestPermission(): Promise<PermissionResponse>

Calling this before capture is optional: both takePicture and recordVideo auto-request the CAMERA permission on Android (iOS auto-requests at the AVCaptureDevice layer), so you only need requestPermission to gate your own UI ahead of time or to inspect canAskAgain.

Platform notes: on first denial this re-surfaces the OS dialog. Check canAskAgain on the response — when false, the user must change the permission from system Settings.

Camera.getPermissionStatus#

Checks the current camera permission status without prompting.

TypeScript
getPermissionStatus(): Promise<PermissionResponse>

Platform notes: never shows a dialog. Use this for a silent check before deciding whether to call requestPermission.

Camera.isAvailable#

Returns whether the native Camera module is registered in the current build.

TypeScript
isAvailable(): boolean
  • Returnstrue if the module is present, otherwise false.

Platform notes: this is a JS-only check (it does not cross the native bridge and does not test for hardware). A true result means the module was linked; it does not guarantee a usable camera device.

Types#

CameraOptions#

Options for Camera.takePicture. All fields are optional.

TypeScript
interface CameraOptions {
  /** 'front' or 'back' camera (iOS only). */
  facing?: 'front' | 'back';
  /** JPEG quality 0-1 (default 0.8, iOS only). */
  quality?: number;
  /** Max width in pixels (reserved — not yet applied). */
  maxWidth?: number;
  /** Max height in pixels (reserved — not yet applied). */
  maxHeight?: number;
}
  • facing — which camera to use. iOS only — Android's intent ignores it (the user can switch cameras in its UI).
  • quality — JPEG quality from 0 to 1 (default 0.8). iOS only.
  • maxWidth / maxHeight — reserved for forward compatibility; not yet applied on either platform.

PhotoResult#

The result returned by Camera.takePicture.

TypeScript
interface PhotoResult {
  /** File URI of the captured photo (`file://` iOS, `content://` Android). */
  uri: string;
  /** Width in pixels (iOS only). */
  width?: number;
  /** Height in pixels (iOS only). */
  height?: number;
  /** File size in bytes (iOS only). */
  fileSize?: number;
  /** Base64-encoded image data (if requested). */
  base64?: string;
}
  • uri — the captured JPEG, normalized to a scheme: file:// on iOS, content:// on Android. Always present on success.
  • width / height / fileSize — best-effort metadata (iOS only — Android's intent doesn't report dimensions).
  • base64 — optional base64-encoded image data; not populated by either current native implementation.

This is the success shape. On cancel the resolved value is CameraCancelled ({ cancelled: true }, no uri); on failure the call throws. Narrow on uri before reading the other fields — see the three-outcome contract.

CameraVideoOptions#

Options for Camera.recordVideo. All fields are optional.

TypeScript
interface CameraVideoOptions {
  /** 'front' or 'back' camera (iOS only). */
  facing?: 'front' | 'back';
  /** Max recording length in milliseconds (iOS only). */
  maxDurationMs?: number;
}
  • facing — which camera to use. iOS only — Android's ACTION_VIDEO_CAPTURE intent ignores it.
  • maxDurationMs — recording cap, honored on iOS (videoMaximumDuration); Android's intent exposes no duration cap.

VideoResult#

The success result returned by Camera.recordVideo.

TypeScript
interface VideoResult {
  /** File URI of the recorded clip (`file://` iOS, `content://` Android). */
  uri: string;
  /** Clip duration in milliseconds (if the platform reports it). */
  durationMs?: number;
  /** Width in pixels (if reported). */
  width?: number;
  /** Height in pixels (if reported). */
  height?: number;
  /** File size in bytes (if reported). */
  fileSize?: number;
}
  • uri — the recorded clip, normalized to a scheme (file:// iOS, content:// Android). Loadable directly by @sigx/lynx-video's VideoPlayer.
  • durationMs / width / height / fileSize — best-effort metadata when the platform reports it.

CameraCancelled#

The shape resolved (not thrown) when the user dismisses the camera without capturing — shared by both takePicture and recordVideo.

TypeScript
interface CameraCancelled {
  cancelled: true;
  uri?: undefined;
}

uri is typed as undefined so callers can narrow on result.uri to tell a successful capture from a cancel.

PermissionResponse#

The response shape for Camera.requestPermission and Camera.getPermissionStatus. Re-exported type-only from @sigx/lynx-core.

TypeScript
interface PermissionResponse {
  /** Current permission status. */
  status: PermissionStatus;
  /**
   * Whether the app can show the OS permission dialog again.
   * `false` when the user selected "Don't ask again" (Android) or
   * after the first denial (iOS — user must go to Settings).
   */
  canAskAgain: boolean;
}
  • status — the current permission status (see PermissionStatus below).
  • canAskAgain — whether the OS dialog can be shown again.

PermissionStatus is defined in @sigx/lynx-core and is not re-exported from this package. If you need the literal union, import it directly:

TypeScript
import type { PermissionStatus } from '@sigx/lynx-core';
// type PermissionStatus = 'granted' | 'denied' | 'undetermined' | 'blocked';

Platform note: the iOS native layer can additionally emit 'restricted' and 'unknown', which fall outside the declared union — handle unexpected values defensively.