Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/slimy-foxes-hide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@shopify/ui-extensions': minor
---

Add Camera API types
7 changes: 7 additions & 0 deletions packages/ui-extensions/src/surfaces/point-of-sale/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@ export type {ActionApi, ActionApiContent} from './api/action-api/action-api';
export type {StandardApi} from './api/standard/standard-api';
export type {ActionTargetApi} from './api/action-target-api/action-target-api';

export type {
CameraApi,
CameraApiContent,
CameraMediaOptions,
CameraMediaResponse,
} from './api/camera-api/camera-api';

export type {
ConnectivityStateSeverity,
ConnectivityState,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import {ScannerApi} from '../scanner-api/scanner-api';
import {StandardApi} from '../standard/standard-api';
import {CameraApi} from '../camera-api/camera-api';

export type ActionTargetApi<T> = {[key: string]: any} & {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe I missed it but we only want to allow the camera to be triggered from action targets? Is there a reason why we don't want the api accessible from tiles or blocks?

extensionPoint: T;
} & StandardApi<T> &
ScannerApi;
ScannerApi &
CameraApi;
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
export interface CameraMediaOptions {
/**
* The camera that will be active when the camera interface first opens.
* - `'user'`: The front-facing camera
* - `'environment'`: The rear-facing camera
* @defaultValue 'environment'
*/
facingMode?: 'user' | 'environment';
/**
* The maximum width (0 to 1080) of the image in pixels. Resizes the image to this width if it is larger.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should it be (1 to 1080)

What happens when users put a value of 0?

* @defaultValue 1080
*/
maxWidth?: number;
/**
* The maximum height (0 to 1080) of the image in pixels. Resizes the image to this height if it is larger.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here

* @defaultValue 1080
*/
maxHeight?: number;
/**
* The quality of the image returned. Percentile value between 0 and 1.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, whats 0 quality do?

* @defaultValue 0.9
*/
quality?: number;
}

export interface CameraMediaResponse {
/** The image data as base64 string. */
base64: string;
/** The width of the image in pixels. */
width: number;
/** The height of the image in pixels. */
height: number;
/** The file size of the image in bytes. */
fileSize: number;
/** The MIME type of the image. */
type: string;
}

export interface CameraApiContent {
/**
* Launch the device's camera to take a photo.
*
* @param options the options for the camera media.
* @returns Promise<CameraMediaResponse> that resolves when the POS has necessary permissions to access the camera and the media is captured.
*/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we be clear on the promise reject reasons? Maybe something like:

 * @throws {Error} when camera permission is denied by the user
 * @throws {Error} when the user cancels the photo capture
 * @throws {Error} when the device has no available camera

takePhoto: (options?: CameraMediaOptions) => Promise<CameraMediaResponse>;
}

export interface CameraApi {
camera: CameraApiContent;
}