Session.activateAR ​Contract 2.0.0 · package sha256
a857eca95b35921109faf997094bb4192f12527d9d0fcd4be7e97f06425bad6e· generated fromconfigurator-runtime.d.tsbyservices/onsite-scripter/scripts/build-contract-docs.mjs; edit the source, not this file.
Method of Session · inherited by testing.FakeSession · stable · since 2.0.0 · called as session.activateAR
activateAR(options?: ActivateAROptions): Promise<ActivateARReport>;
Launches AR for the product. Status changes fire 'ar:status'. Call it from the shopper's tap
or click: WebXR needs that gesture's user activation (about 5 s in Chromium). The runtime loads
its AR code at idle once the product is on screen, so a tap after that waits for no download;
a tap before it opens the native viewer, never the in-page one.
Read info().ar.modes before showing an AR control; a tap on a device with no mode resolves
{ launched: false, reason: 'unsupported' }.
Routing (spec section 5.11): on Android the in-page WebXR viewer opens only for an account that
opts in (ar.place.android: 'holostep' in its published layer), with the platform's AR switch
on, no glbUrl, a device and embed that pass the probe, and the tap's activation (the other
conditions: spec section 5.11). Every other Android call opens Scene Viewer with glbUrl or,
without one, with the product's public plain twin when the product is one encrypted model with
an http(s) plainGlbUrl; else it resolves reason: 'unsupported'. WebXR never loads
glbUrl. On iOS and iPadOS Holostep's in-page AR opens for an account whose published layer
sets ar.place.ios: 'holostep' (browsers) or ar.place.inpage: 'fallback' (app shells), with
the platform's xr.place and xr.inpage switches on; Quick Look is its fallback, and in an
app shell the fallback is an escape sheet that resolves reason: 'unsupported'. Quick Look
gets usdzUrl (or else the runtime's own USDZ export: ActivateAROptions.usdzUrl), never a
GLB, in Safari and in Chrome, Firefox, Edge and DuckDuckGo on iOS alike.
ActivateARReport.mode 'webxr' names Holostep's in-page viewer on either route (WebXR on
Android, the camera tracker on iOS). Where the escape sheet is the only route, modes lists
'webxr', so the AR control shows and its tap opens the sheet, as 1.x does.
A WebXR session draws its own copy of the committed product, built at launch (what it draws
over the camera feed: spec section 5.11). Staged writes and holds never reach it, so a
transaction during AR never blanks it; a committed material change of a part it holds does,
and a capture meanwhile renders the live scene.
Quick Look and Scene Viewer get the newest committed state too (the runtime's own USDZ or the
files you pass): a write still loading when the shopper taps (a fabric pick whose map is
still downloading) is not in that copy, though the page shows it a moment later. Don't await
the pick inside the tap (its user activation would lapse): keep the AR control off while a
write the shopper made is pending, as the example's pick does.
A rejected WebXR requestSession never falls through to another viewer inside the call: it
resolves, and the next viewer needs a new tap. A call while another is pending or active
returns that call's Promise. Scene Viewer and Quick Look report no failure at the launch.
ActivateARReport.mode names the one that opened.
When it resolves: WebXR once its session starts; Scene Viewer launched: true when the page
turns hidden, or { launched: false, reason: 'error' } when Chrome returns to the runtime's
fallback hash (no Google app, or a launch outside the gesture), whichever comes first within
2 s of the launch; after 2 s with neither it resolves launched: true, and a later return to the hash
still fires 'ar:status' with 'error'. Quick
Look resolves launched: true once its rel="ar" link is clicked: iOS reports no failure.
Every failure, before or after the call resolves, fires 'ar:status' with 'error'.
Errors: a failed launch resolves { launched: false, reason: 'error' }, and a declined AR
prompt or a close before AR started reason: 'cancelled'; only invalid input rejects
(HoloInputError).
| Option | Type | Default | What it does |
|---|---|---|---|
glbUrl |
string |
undefined (an opted-in account's in-page viewer shows a copy of the committed product; else Scene Viewer gets the product's plain twin, or the call resolves 'unsupported': spec section 5.11) | The GLB Scene Viewer opens: an http(s) URL, never a .holo (Scene Viewer runs outside the page, so it can't read a blob: URL either). |
occlusion |
boolean |
true (Scene Viewer's own) | Scene Viewer's depth occlusion. |
overlayRoot |
HTMLElement |
undefined (Holostep's screens alone, in a layer over the whole page, removed when AR closes) | Your own UI over the camera in Holostep's in-page AR (a swatch strip, a part toggle, add to cart): an element you created before the call. |
scale |
'auto' | 'fixed' |
'auto' | 'fixed' keeps the product at true size, so the shopper can't pinch-scale it (Scene Viewer resizable=false, Quick Look allowsContentScaling=0, and no… |
title |
string |
undefined (the account's AR title, else the viewer's own) | The name the AR viewer shows: Scene Viewer's title, and the Quick Look banner's title where the account turns the banner on. |
ui |
'default' | 'headless' |
'default' | 'default' shows Holostep's AR screens; 'headless' lets the page draw its own: Holostep's in-page AR then shows only the camera and the product (no coaching… |
usdzUrl |
string |
undefined (the runtime exports one) | The USDZ iOS Quick Look opens: a hosted http(s) URL, or a blob: URL of a USDZ, such as one made from session.export({ format: 'usdz' }) (an app that… |
Imports: values (has, validate, the Holo*Error classes, the pure helpers) from @holostep-configurators/runtime-client, types from @holostep-configurators/runtime-client/contract, /math and /testing names from those entries; boot from the runtime module the root's loadRuntimeAtFloor resolves to. A type your page defines is your app's: declare it there, never import it from the package.
Compiled under the contract's strict settings (examples/declaration/05-Session.activateAR.ts):
import type { Session } from '@holostep-configurators/runtime-client/contract';
declare const session: Session;
declare const signal: AbortSignal;
declare const files: { glb: string; usdz: string };
declare function showArButton(visible: boolean): void;
declare function toast(text: string): void;
// This page passes its own files, so a viewer `fileModes` lists opens too (an encrypted
// product without a public plain twin leaves Scene Viewer out of `modes` only).
const canAr = () => {
const { modes, fileModes } = session.info().ar;
return modes.length > 0 || fileModes.length > 0;
};
showArButton(canAr());
// 'webxr' can join after boot: follow the modes, in the same task as the read above.
session.on('ar:modes', () => showArButton(canAr()), { signal });
// 'error' also comes after the call resolved, when Scene Viewer bounces back late.
session.on('ar:status', ({ status }) => {
if (status === 'error') toast('AR did not start on this phone.');
}, { signal });
// In the button's click handler (the shopper's gesture):
const report = await session.activateAR({ glbUrl: files.glb, usdzUrl: files.usdz, title: 'Pergola' });
// An escape sheet (an app shell) resolves 'unsupported' but keeps 'webxr' listed: keep the
// control there; any other 'unsupported' (e.g. no hosted file for the native viewer) hides it.
if (!report.launched && report.reason === 'unsupported') {
showArButton(session.info().ar.modes.includes('webxr'));
}
// A pick still loading is not in Quick Look's or Scene Viewer's copy: keep the control off
// until the shopper's writes have committed.
let loading = 0;
export async function pick(group: string, material: string): Promise<void> {
loading++;
showArButton(false);
try {
await session.select(group, material);
} finally {
if (--loading === 0) showArButton(canAr());
}
}
| Rule | Result |
|---|---|
| 1. Neutral name | pass: activateAR names no product |
| 2. A precedent | pass: model-viewer (ar, camera-orbit, auto-rotate) (row G18); Unity Animator.Rebind (row G18); Google Scene Viewer intent (title, resizable) (row G59) |
| 3. Two apps, or labs | pass: 24 apps (ledger: app-04c2774145, app-4762caacdc, app-4f16d2f6da, app-ceb4eccc72, app-f9a32142f1, app-fb16dd1985, app-fc07850558, app-fd09090420; fleet cross-check: app-04c2774145, app-37356bf09f, app-4762caacdc, app-4f16d2f6da, app-4fd23bc869, app-510d750508, app-59c5b5751e, app-822bb9d6aa and 16 more) |
| 4. The cheaper fix first | decided per need in Appendix B: rows G18, G59 at tier stable (a member only where no rule, data, asset or app code serves the need) |