@egjs/view3d
Version:
Fast & Customizable glTF 3D model viewer, packed with full of features!
179 lines (155 loc) • 8.56 kB
text/typescript
/*
* Copyright (c) 2020 NAVER Corp.
* egjs projects are licensed under the MIT license
*/
import View3D from "../View3D";
import View3DError from "../core/View3DError";
import { IS_IOS } from "../const/browser";
import { QUICK_LOOK_SUPPORTED } from "../const/xr";
import { AR_SESSION_TYPE, EVENTS, QUICK_LOOK_APPLE_PAY_BUTTON_TYPE, QUICK_LOOK_CUSTOM_BANNER_SIZE } from "../const/external";
import ERROR from "../const/error";
import { LiteralUnion, OptionGetters, ValueOf } from "../type/utils";
import ARSession from "./ARSession";
/**
* @interface
* @param {boolean} [allowsContentScaling=true] Whether to allow content scaling.
* @param {string | null} [canonicalWebPageURL=null] The web URL to share when the user invokes the share sheet. If `null` is given, the USDZ file will be shared.
* @param {string | null} [applePayButtonType=null] Type of the apple pay button in the banner. See {@link QUICK_LOOK_APPLE_PAY_BUTTON_TYPE}
* @param {string | null} [callToAction=null] A text that will be displayed instead of Apple Pay Button. See {@link https://developer.apple.com/documentation/arkit/adding_an_apple_pay_button_or_a_custom_action_in_ar_quick_look#3405143 Official Guide Page}
* @param {string | null} [checkoutTitle=null] Title of the previewed item. See {@link https://developer.apple.com/documentation/arkit/adding_an_apple_pay_button_or_a_custom_action_in_ar_quick_look#3405142 Official Guide Page}
* @param {string | null} [checkoutSubtitle=null] Subtitle of the previewed item. See {@link https://developer.apple.com/documentation/arkit/adding_an_apple_pay_button_or_a_custom_action_in_ar_quick_look#3405142 Official Guide Page}
* @param {string | null} [price=null] Price of the previewed item. See {@link https://developer.apple.com/documentation/arkit/adding_an_apple_pay_button_or_a_custom_action_in_ar_quick_look#3405142 Official Guide Page}
* @param {string | null} [custom=null] Custom URL to the banner HTML. See {@link https://developer.apple.com/documentation/arkit/adding_an_apple_pay_button_or_a_custom_action_in_ar_quick_look#3402837 Official Guide Page}
* @param {string | null} [customHeight=null] Height of the custom banner. See {@link QUICK_LOOK_CUSTOM_BANNER_SIZE}
*/
export interface QuickLookSessionOptions {
allowsContentScaling: boolean;
canonicalWebPageURL: string | null;
applePayButtonType: LiteralUnion<ValueOf<typeof QUICK_LOOK_APPLE_PAY_BUTTON_TYPE>, string> | null;
callToAction: string | null;
checkoutTitle: string | null;
checkoutSubtitle: string | null;
price: string | null;
custom: string | null;
customHeight: LiteralUnion<ValueOf<typeof QUICK_LOOK_CUSTOM_BANNER_SIZE>, string> | null;
}
/**
* AR Session using Apple AR Quick Look Viewer
* @see https://developer.apple.com/augmented-reality/quick-look/
*/
class QuickLookSession implements ARSession, OptionGetters<QuickLookSessionOptions> {
/**
* Return the availability of QuickLookSession.
* QuickLook AR is available on iOS12+
* @returns {Promise} A Promise that resolves availability of this session(boolean).
*/
public static isAvailable() {
return Promise.resolve(QUICK_LOOK_SUPPORTED() && IS_IOS());
}
public static readonly type = AR_SESSION_TYPE.QUICK_LOOK;
// Options
// As those values are referenced only while entering the session, so I'm leaving this values public
public allowsContentScaling: QuickLookSessionOptions["allowsContentScaling"];
public canonicalWebPageURL: QuickLookSessionOptions["canonicalWebPageURL"];
public applePayButtonType: QuickLookSessionOptions["applePayButtonType"];
public callToAction: QuickLookSessionOptions["callToAction"];
public checkoutTitle: QuickLookSessionOptions["checkoutTitle"];
public checkoutSubtitle: QuickLookSessionOptions["checkoutSubtitle"];
public price: QuickLookSessionOptions["price"];
public custom: QuickLookSessionOptions["custom"];
public customHeight: QuickLookSessionOptions["customHeight"];
private _view3D: View3D;
/**
* Create new instance of QuickLookSession
* @param {View3D} view3D Instance of the View3D
* @param {object} [options={}] Quick Look options
* @param {boolean} [options.allowsContentScaling=true] Whether to allow content scaling.
* @param {string | null} [options.canonicalWebPageURL=null] The web URL to share when the user invokes the share sheet. If `null` is given, the USDZ file will be shared.
* @param {string | null} [options.applePayButtonType=null] Type of the apple pay button in the banner. See {@link QUICK_LOOK_APPLE_PAY_BUTTON_TYPE}
* @param {string | null} [options.callToAction=null] A text that will be displayed instead of Apple Pay Button. See {@link https://developer.apple.com/documentation/arkit/adding_an_apple_pay_button_or_a_custom_action_in_ar_quick_look#3405143 Official Guide Page}
* @param {string | null} [options.checkoutTitle=null] Title of the previewed item. See {@link https://developer.apple.com/documentation/arkit/adding_an_apple_pay_button_or_a_custom_action_in_ar_quick_look#3405142 Official Guide Page}
* @param {string | null} [options.checkoutSubtitle=null] Subtitle of the previewed item. See {@link https://developer.apple.com/documentation/arkit/adding_an_apple_pay_button_or_a_custom_action_in_ar_quick_look#3405142 Official Guide Page}
* @param {string | null} [options.price=null] Price of the previewed item. See {@link https://developer.apple.com/documentation/arkit/adding_an_apple_pay_button_or_a_custom_action_in_ar_quick_look#3405142 Official Guide Page}
* @param {string | null} [options.custom=null] Custom URL to the banner HTML. See {@link https://developer.apple.com/documentation/arkit/adding_an_apple_pay_button_or_a_custom_action_in_ar_quick_look#3402837 Official Guide Page}
* @param {string | null} [options.customHeight=null] Height of the custom banner. See {@link QUICK_LOOK_CUSTOM_BANNER_SIZE}
*/
public constructor(view3D: View3D, {
allowsContentScaling = true,
canonicalWebPageURL = null,
applePayButtonType = null,
callToAction = null,
checkoutTitle = null,
checkoutSubtitle = null,
price = null,
custom = null,
customHeight = null
}: Partial<QuickLookSessionOptions> = {}) {
this._view3D = view3D;
this.allowsContentScaling = allowsContentScaling;
this.canonicalWebPageURL = canonicalWebPageURL;
this.applePayButtonType = applePayButtonType;
this.callToAction = callToAction;
this.checkoutTitle = checkoutTitle;
this.checkoutSubtitle = checkoutSubtitle;
this.price = price;
this.custom = custom;
this.customHeight = customHeight;
}
/**
* Enter QuickLook AR Session
*/
public enter() {
const view3D = this._view3D;
const file = view3D.iosSrc;
if (!file) {
return Promise.reject(new View3DError(ERROR.MESSAGES.FILE_NOT_SUPPORTED(`${file}`), ERROR.CODES.FILE_NOT_SUPPORTED));
}
const canonicalWebPageURL = this.canonicalWebPageURL;
const custom = this.custom;
const currentHref = window.location.href;
const anchor = document.createElement("a") ;
anchor.setAttribute("rel", "ar");
anchor.appendChild(document.createElement("img"));
const hashObj = Object.entries({
applePayButtonType: this.applePayButtonType,
callToAction: this.callToAction,
checkoutTitle: this.checkoutTitle,
checkoutSubtitle: this.checkoutSubtitle,
price: this.price,
customHeight: this.customHeight
}).reduce((obj, [key, value]) => {
if (value) {
obj[key] = value as string;
}
return obj;
}, {} as Record<string, string>);
const usdzURL = new URL(file, currentHref);
if (!this.allowsContentScaling) {
hashObj.allowsContentScaling = "0";
}
if (canonicalWebPageURL) {
hashObj.canonicalWebPageURL = new URL(canonicalWebPageURL, currentHref).href;
}
if (custom) {
hashObj.custom = new URL(custom, currentHref).href;
}
usdzURL.hash = new URLSearchParams(hashObj).toString();
anchor.setAttribute("href", usdzURL.href);
anchor.addEventListener("message", evt => {
if ((evt as any).data === "_apple_ar_quicklook_button_tapped") {
// User tapped either Apple pay button / Custom action button
view3D.trigger(EVENTS.QUICK_LOOK_TAP, {
...evt,
type: EVENTS.QUICK_LOOK_TAP,
target: view3D
});
}
}, false);
anchor.click();
return Promise.resolve();
}
public exit() {
return Promise.resolve();
}
}
export default QuickLookSession;