Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
17beabe
chore: clean up some formatting issues
jasonfill Jun 14, 2025
340d6f7
chore: fix additional formatting issues
jasonfill Jun 14, 2025
1eec65d
chore: fix more formatting
jasonfill Jun 14, 2025
e0f224f
chore: fix some formatting items
jasonfill Jun 14, 2025
a1d933a
chore: additional formatting changes
jasonfill Jun 14, 2025
e6e03b5
chore: some resolutions were removed, replaced them
jasonfill Jun 14, 2025
3c451ba
chore: formatting
jasonfill Jun 14, 2025
970b2cd
chore: remove duplicate items in package
jasonfill Jun 14, 2025
221e986
chore: formatting
jasonfill Jun 15, 2025
982d2fb
chore: add ability to provide default device label to select that dev…
riasatali42 Jul 16, 2025
e1afc54
chore: added callback method for camera changed and if not default ca…
riasatali42 Jul 16, 2025
d9e9829
chore: added selectableDevices array check
riasatali42 Jul 17, 2025
9e50956
chore: added default device info in machine tests for unit testing
riasatali42 Jul 17, 2025
cb855f1
chore: default device info for unit testing default device pass in
riasatali42 Jul 21, 2025
7bf2668
chore: unit tests added for default device not found and camera switc…
riasatali42 Jul 22, 2025
be062ed
chore: added device selection priority unit tests
riasatali42 Jul 22, 2025
7120b36
docs: added changeset for minor changes
riasatali42 Jul 22, 2025
a89bfd9
fix: fixed mock device info after resolving merge conflicts
riasatali42 Jul 28, 2025
f752e2d
chore: added updated unit tests for passed in device label, callCamer…
riasatali42 Jul 28, 2025
66d59c3
fix: fixed ESlint issue on livenesscameramodule
riasatali42 Jul 29, 2025
eef17a2
fix: fixed eslint issue on adding type on error and replaced operator
riasatali42 Jul 29, 2025
b92d62d
fix: resolved PR feedback, added console error, removed device info f…
riasatali42 Aug 7, 2025
c33f155
chore: merged with main branch and added e2e testing for react-livene…
riasatali42 Sep 3, 2025
c5e9cd9
chore: Added step for I see the Device ID selectfield, added e2e test…
riasatali42 Sep 4, 2025
12ccec5
chore: removed deviceLabel, cameraNotFound callback and onCamerChange…
riasatali42 Sep 30, 2025
c095a5a
chore: removed all logics of deviceLabel pass in, onCameraChange and …
riasatali42 Sep 30, 2025
77b2dfc
chore: removed onCameraChange and defaultCameraNotFound callback from…
riasatali42 Oct 3, 2025
19a8bae
chore: added removed code for cameraChange
riasatali42 Oct 3, 2025
2bc3e21
chore: DEFAULT_CAMERA_NOT_FOUND_ERROR error added for react-liveness
riasatali42 Oct 6, 2025
3b89f7e
chore: added new unit tests for passing default device id and if not …
riasatali42 Oct 7, 2025
032bc12
chore: added device id related e2e tests, removed device label pass i…
riasatali42 Oct 7, 2025
9fb0ce9
chore: removed unnecessary lines
riasatali42 Oct 8, 2025
c40406a
chore: replaced deviceId from props to config props of LivenessDetector
riasatali42 Oct 9, 2025
5dc17c5
chore: added deviceId in the next example app of LivenessDetector to …
riasatali42 Oct 9, 2025
d6c3638
chore: updated next-example to support default deviceId using params
riasatali42 Oct 9, 2025
801a5da
chore: removed unnecessary lines from next-example of pass in default…
riasatali42 Oct 9, 2025
32e3175
chore: updated e2e test for invald device pass in in liveness detection
riasatali42 Oct 9, 2025
ac4e22f
chore: changeset updated
riasatali42 Oct 9, 2025
40e9086
chore: removed unnecessary onUserTimeout callback and update e2e test…
riasatali42 Oct 9, 2025
c9f6882
chore: added deviceInfo while calling the onError callback in livenes…
riasatali42 Oct 14, 2025
083b11e
chore: added unit tests for passing deviceInfo while calling onError …
riasatali42 Oct 15, 2025
2ec7e77
fix: fixed lint issue by removing quote sign and added " tag
riasatali42 Oct 23, 2025
ae9671b
chore: removed unnecessary codes from liveness test code
riasatali42 Oct 29, 2025
8c9325e
fix: resolved unit test issue due to branch rebase and cleaned unnece…
riasatali42 Oct 30, 2025
03dd642
fix: added deviceInfo type for liveness checking
riasatali42 Oct 30, 2025
6a7bf88
fix: correct select field locator in liveness e2e test
marajulEnosis Nov 4, 2025
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/chilly-olives-dress.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@aws-amplify/ui-react-liveness': minor
---

Pass default device info using ID. Emit detailed device info on liveness complete. DEFAULT_CAMERA_NOT_FOUND_ERROR added in onError callback if device not found with deviceId.
2 changes: 1 addition & 1 deletion examples/angular/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,4 @@
"@types/jasmine"
]
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export default function LivenessDefault({
} = useLiveness(challengeType);

if (createLivenessSessionApiError) {
console.error(createLivenessSessionApiError);
return <div>Some error occurred...</div>;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
import React from 'react';
import {
View,
Flex,
Loader,
Text,
Card,
Heading,
Divider,
} from '@aws-amplify/ui-react';
import { FaceLivenessDetectorCore } from '@aws-amplify/ui-react-liveness';
import { useLiveness } from '../components/useLiveness';
import { ChallengeSelection } from '../components/ChallengeSelection';
import { SessionIdAlert } from '../components/SessionIdAlert';
import LivenessInlineResults from '../components/LivenessInlineResults';

const FACE_MOVEMENT_AND_LIGHT_CHALLENGE = 'FaceMovementAndLightChallenge';
const FACE_MOVEMENT_CHALLENGE = 'FaceMovementChallenge';

const SUPPORTED_CHALLENGES_TYPES = [
FACE_MOVEMENT_AND_LIGHT_CHALLENGE,
FACE_MOVEMENT_CHALLENGE,
];

export default function PassInDefaultDeviceExample() {
const [challengeType, setChallengeType] = React.useState(
FACE_MOVEMENT_AND_LIGHT_CHALLENGE
);

// Test hooks for e2e testing
const [testDeviceId, setTestDeviceId] = React.useState<string | null>(null);
const [currentDeviceInfo, setCurrentDeviceInfo] = React.useState<any>(null);

// Config to optionally preselect a camera by deviceId (e.g., via URL query).
const livenessConfig = React.useMemo(() => {
// Read from query string ?deviceId=... if present
if (typeof window !== 'undefined') {
const params = new URLSearchParams(window.location.search);
const qDeviceId = params.get('deviceId');
if (qDeviceId) {
return { deviceId: qDeviceId } as { deviceId?: string };
}
}
// No default; let SDK choose if not provided
return { deviceId: undefined } as { deviceId?: string };
}, []);

// Validate provided deviceId and expose to existing e2e hooks
React.useEffect(() => {
const configuredId = livenessConfig?.deviceId;
if (!configuredId || typeof window === 'undefined') return;

let cancelled = false;
(async () => {
try {
// Enumerate devices to verify presence
if (navigator?.mediaDevices?.enumerateDevices) {
const devices = await navigator.mediaDevices.enumerateDevices();
const found = devices.some(
(d) => d.kind === 'videoinput' && d.deviceId === configuredId
);
if (!cancelled) {
(window as any).testDeviceIdIsValid = found;
setTestDeviceId(configuredId);
}
} else {
// Assume not valid if enumeration is unavailable
(window as any).testDeviceIdIsValid = false;
setTestDeviceId(configuredId);
}
} catch (e) {
// Fallback to not valid on error
(window as any).testDeviceIdIsValid = false;
setTestDeviceId(configuredId);
}
})();
}, [livenessConfig?.deviceId]);

// Setup e2e hooks
React.useEffect(() => {
if (typeof window !== 'undefined') {
// Expose setters and current device info
(window as any).setTestDeviceId = setTestDeviceId;
(window as any).currentDeviceInfo = currentDeviceInfo;

// Check for a deviceId seeded by tests
const testId = (window as any).testDeviceId;
if (testId) {
setTestDeviceId(testId);
}
}
}, [currentDeviceInfo]);

const {
getLivenessResponse,
createLivenessSessionApiError,
createLivenessSessionApiData,
createLivenessSessionApiLoading,
handleGetLivenessDetection,
stopLiveness,
} = useLiveness(challengeType);

if (createLivenessSessionApiError) {
return <div>Some error occurred...</div>;
}

function onUserCancel() {
stopLiveness();
}

return (
<View maxWidth="800px" margin="0 auto">
{createLivenessSessionApiLoading ? (
<Flex justifyContent="center" alignItems="center">
<Loader /> <Text as="span">Loading...</Text>
</Flex>
) : (
<Flex direction="column" gap="xl">
<Card variation="elevated" padding="large">
<Heading level={3} marginBottom="medium">
Pass-in Default Device Example
</Heading>
<Text marginBottom="large" color="gray">
This example demonstrates passing a default camera via a config
prop (for example, using the URL query &quot;?deviceId=...&quot;).
If the provided deviceId matches an available camera, that device
will be auto-selected for liveness. If not found, the example will
fall back to another available camera.
</Text>
</Card>

<ChallengeSelection
selectedChallenge={challengeType}
onChange={setChallengeType}
challengeList={SUPPORTED_CHALLENGES_TYPES}
/>

<SessionIdAlert
sessionId={createLivenessSessionApiData['sessionId']}
/>

{/* Test Device Configuration Display */}
{testDeviceId && (
<Card variation="outlined" padding="medium">
<Heading level={4} marginBottom="small">
Test Device Configuration
</Heading>
<Text>Test Device ID: {testDeviceId}</Text>
{currentDeviceInfo && (
<div>
<Text fontWeight="bold" marginTop="small">
Current Device Info:
</Text>
<Text>Device ID: {currentDeviceInfo.deviceId}</Text>
<Text>Label: {currentDeviceInfo.label}</Text>
<Text>Group ID: {currentDeviceInfo.groupId}</Text>
</div>
)}
</Card>
)}

{!!getLivenessResponse ? (
<LivenessInlineResults
getLivenessResponse={getLivenessResponse}
onUserCancel={onUserCancel}
/>
) : null}

<Divider />

<Flex gap="0" direction="column" position="relative">
{!getLivenessResponse ? (
<FaceLivenessDetectorCore
sessionId={createLivenessSessionApiData['sessionId']}
region={'us-east-1'}
onUserCancel={onUserCancel}
config={livenessConfig}
onAnalysisComplete={async () => {
// Mock device info for testing
const mockDeviceInfo = {
deviceId: testDeviceId || 'default-camera',
label: testDeviceId
? `Camera for ${testDeviceId}`
: 'Default Camera',
groupId: 'test-group-123',
};

setCurrentDeviceInfo(mockDeviceInfo);

// Expose to window for e2e testing
if (typeof window !== 'undefined') {
(window as any).currentDeviceInfo = mockDeviceInfo;
(window as any).onAnalysisComplete = () => mockDeviceInfo;
}

await handleGetLivenessDetection(
createLivenessSessionApiData['sessionId']
);
}}
onError={(livenessError) => {
console.error('Liveness error:', livenessError);
}}
/>
) : null}
</Flex>
</Flex>
)}
</View>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import dynamic from 'next/dynamic';
import React from 'react';

import { Amplify } from 'aws-amplify';
import awsExports from '@environments/liveness/liveness-environment/src/aws-exports';

import Layout from '../components/Layout';
import PassInDefaultDeviceExample from './PassInDefaultDeviceExample';

Amplify.configure({
...awsExports,
// Analytics: { autoSessionRecord: false },
});

const App = () => {
return (
<Layout>
<PassInDefaultDeviceExample />
</Layout>
);
};

export default dynamic(() => Promise.resolve(App), {
ssr: false,
});
2 changes: 1 addition & 1 deletion examples/vue/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,4 @@
"rimraf": "^5.0.0",
"vite-plugin-pages": "^0.25.0"
}
}
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
"**/@aws-amplify/ui-angular-example/**/codelyzer/**/@angular/core": "10.2.5",
"**/@angular-devkit/build-angular/minimatch": "3.0.5",
"**/@angular-devkit/build-angular/webpack": "^5.76.0",
"**/@angular-devkit/build-angular/webpack-dev-server/express/path-to-regexp": "0.1.12",
"**/@size-limit/webpack/webpack": "^5.76.0",
"**/serve/serve-handler/minimatch": "3.0.5",
"**/serve/serve-handler/path-to-regexp": "3.3.0",
Expand Down
Loading
Loading