@shopware-ag/dive
Version:
Shopware Spatial Framework
155 lines (134 loc) • 4.92 kB
text/typescript
export enum WebXRUnsupportedReason {
'UNKNWON_ERROR' = 0,
'NO_HTTPS' = 1,
'IMMERSIVE_AR_NOT_SUPPORTED_BY_DEVICE' = 2,
'AR_SESSION_NOT_ALLOWED' = 3,
}
export class DIVEInfo {
private static _supportsWebXR: boolean | null = null;
private static _webXRUnsupportedReason: WebXRUnsupportedReason | null =
null;
/**
*
* @returns The system the user is using. Possible values are "Android", "iOS", "Windows", "MacOS", "Linux" or "Unknown".
*/
public static GetSystem(): string {
const platform = navigator.platform;
if (/Android/.test(navigator.userAgent)) {
return 'Android';
} else if (/iPhone|iPad|iPod/.test(navigator.userAgent)) {
return 'iOS';
} else if (platform.startsWith('Win')) {
return 'Windows';
} else if (platform.startsWith('Mac')) {
return 'MacOS';
} else if (platform.startsWith('Linux')) {
return 'Linux';
} else {
return 'Unknown';
}
}
/**
* @returns A promise that resolves to a boolean indicating whether the user's device supports WebXR.
*/
public static async GetSupportsWebXR(): Promise<boolean> {
if (this._supportsWebXR !== null) {
return this._supportsWebXR;
}
// check if XRSystem is available && if https enabled
if (!navigator.xr) {
this._supportsWebXR = false;
if (window.isSecureContext === false) {
this._webXRUnsupportedReason = WebXRUnsupportedReason.NO_HTTPS;
} else {
this._webXRUnsupportedReason =
WebXRUnsupportedReason.UNKNWON_ERROR;
}
return this._supportsWebXR;
}
// Check if immersive-vr session mode is supported
try {
const supported =
await navigator.xr!.isSessionSupported('immersive-ar');
if (!supported) {
this._webXRUnsupportedReason =
WebXRUnsupportedReason.IMMERSIVE_AR_NOT_SUPPORTED_BY_DEVICE;
}
this._supportsWebXR = supported;
} catch (error) {
this._supportsWebXR = false;
this._webXRUnsupportedReason =
WebXRUnsupportedReason.AR_SESSION_NOT_ALLOWED;
}
return this._supportsWebXR;
}
/**
* @returns The reason why WebXR is not supported on the user's device. Returns null if WebXR is supported nor not has been checked yet.
*/
public static GetWebXRUnsupportedReason(): WebXRUnsupportedReason | null {
if (this._supportsWebXR === null) {
console.log('WebXR support has not been checked yet.');
return null;
}
return this._webXRUnsupportedReason;
}
/**
* @returns A boolean indicating whether the user's device supports AR Quick Look.
*/
public static GetSupportsARQuickLook(): boolean {
const a = document.createElement('a');
if (a.relList.supports('ar')) {
return true;
}
// fallback check
const userAgent = navigator.userAgent;
// Check if the device is running iOS
const isIOS =
/iPad|iPhone|iPod/.test(userAgent) &&
!(window as unknown as Window & { MSStream?: string }).MSStream;
if (!isIOS) {
return false;
}
// Extract iOS version
const match = userAgent.match(/OS (\d+)_/);
if (!match || match.length < 2) {
return false;
}
const iOSVersion = parseInt(match[1], 10);
// Minimum iOS version for QuickLook support
const minQuickLookVersion = 12;
// Check if the iOS version is supported
if (iOSVersion < minQuickLookVersion) {
return false;
}
// Check for supported browser
const isSupportedBrowser =
/^((?!chrome|android).)*safari|CriOS|FxiOS/i.test(userAgent);
if (isSupportedBrowser) {
return true;
}
// Default to false if none of the conditions are met
return false;
}
/**
* @returns A boolean indicating whether the user's device is a mobile device.
*/
public static get isMobile(): boolean {
return this.GetSystem() === 'Android' || this.GetSystem() === 'iOS';
}
/**
* @returns A boolean indicating whether the user's device is a desktop device.
*/
public static get isDesktop(): boolean {
return !this.isMobile;
}
/**
* @returns A promise that resolves to a boolean indicating whether the user's device is capable of AR.
*/
public static async GetIsARCapable(): Promise<boolean> {
if (this.GetSupportsARQuickLook()) {
return true;
}
return await this.GetSupportsWebXR();
}
}