UNPKG

react-native-adapty

Version:
246 lines 10.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ViewController = void 0; const tslib_1 = require("tslib"); const view_emitter_1 = require("./view-emitter"); const types_1 = require("./types"); const logger_1 = require("../logger"); const adapty_paywall_1 = require("../coders/adapty-paywall"); const bridge_1 = require("../bridge"); const adapty_ui_dialog_config_1 = require("../coders/adapty-ui-dialog-config"); /** * Provides methods to control created paywall view * @public */ class ViewController { /** * Intended way to create a ViewController instance. * It prepares a native controller to be presented * and creates reference between native controller and JS instance * @internal */ static create(paywall, params) { var _a, _b; return tslib_1.__awaiter(this, void 0, void 0, function* () { const ctx = new logger_1.LogContext(); const log = ctx.call({ methodName: 'createPaywallView' }); log.start({ paywall, params }); const view = new ViewController(); const coder = new adapty_paywall_1.AdaptyPaywallCoder(); const methodKey = 'adapty_ui_create_view'; const data = { method: methodKey, paywall: coder.encode(paywall), preload_products: (_a = params.prefetchProducts) !== null && _a !== void 0 ? _a : true, load_timeout: ((_b = params.loadTimeoutMs) !== null && _b !== void 0 ? _b : 5000) / 1000, }; if (params.customTags) { data['custom_tags'] = params.customTags; } if (params.customTimers) { const convertTimerInfo = (timerInfo) => { const formatDate = (date) => { const pad = (num, digits = 2) => { const str = num.toString(); const paddingLength = digits - str.length; return paddingLength > 0 ? '0'.repeat(paddingLength) + str : str; }; const year = date.getUTCFullYear(); const month = pad(date.getUTCMonth() + 1); const day = pad(date.getUTCDate()); const hours = pad(date.getUTCHours()); const minutes = pad(date.getUTCMinutes()); const seconds = pad(date.getUTCSeconds()); const millis = pad(date.getUTCMilliseconds(), 3); return `${year}-${month}-${day}T${hours}:${minutes}:${seconds}.${millis}Z`; }; const result = {}; for (const key in timerInfo) { if (timerInfo.hasOwnProperty(key)) { const date = timerInfo[key]; if (date instanceof Date) { result[key] = formatDate(date); } } } return result; }; data['custom_timers'] = convertTimerInfo(params.customTimers); } const body = JSON.stringify(data); const result = yield view.handle(methodKey, body, 'AdaptyUiView', ctx, log); view.id = result.id; return view; }); } /** * Since constructors in JS cannot be async, it is not * preferred to create ViewControllers in direct way. * Consider using @link{ViewController.create} instead * * @remarks * Creating ViewController this way does not let you * to make native create request and set _id. * It is intended to avoid usage * * @internal */ constructor() { this.unsubscribeAllListeners = null; this.id = null; } handle(method, params, resultType, ctx, log) { return tslib_1.__awaiter(this, void 0, void 0, function* () { try { const result = yield bridge_1.$bridge.request(method, params, resultType, ctx); log.success(result); return result; } catch (error) { /* * Success because error was handled validly * It is a developer task to define which errors must be logged */ log.success({ error }); throw error; } }); } /** * Presents a paywall view as a full-screen modal * * @remarks * Calling `present` upon already visible paywall view * would result in an error * * @throws {AdaptyError} */ present() { return tslib_1.__awaiter(this, void 0, void 0, function* () { const ctx = new logger_1.LogContext(); const log = ctx.call({ methodName: 'present' }); log.start({ _id: this.id }); if (this.id === null) { log.failed({ error: 'no _id' }); throw this.errNoViewReference(); } const methodKey = 'adapty_ui_present_view'; const body = JSON.stringify({ method: methodKey, id: this.id, }); const result = yield this.handle(methodKey, body, 'Void', ctx, log); return result; }); } /** * Dismisses a paywall view * * @throws {AdaptyError} */ dismiss() { return tslib_1.__awaiter(this, void 0, void 0, function* () { const ctx = new logger_1.LogContext(); const log = ctx.call({ methodName: 'dismiss' }); log.start({ _id: this.id }); if (this.id === null) { log.failed({ error: 'no id' }); throw this.errNoViewReference(); } const methodKey = 'adapty_ui_dismiss_view'; const body = JSON.stringify({ method: methodKey, id: this.id, destroy: false, }); yield this.handle(methodKey, body, 'Void', ctx, log); if (this.unsubscribeAllListeners) { this.unsubscribeAllListeners(); } }); } /** * Presents the dialog * * @param {AdaptyUiDialogConfig} config - A config for showing the dialog. * * @remarks * If you provide two actions in the config, be sure `primaryAction` cancels the operation * and leaves things unchanged. * * @returns {Promise<AdaptyUiDialogActionType>} A Promise that resolves to the {@link AdaptyUiDialogActionType} object * * @throws {AdaptyError} */ showDialog(config) { return tslib_1.__awaiter(this, void 0, void 0, function* () { const ctx = new logger_1.LogContext(); const log = ctx.call({ methodName: 'showDialog' }); log.start({ _id: this.id }); if (this.id === null) { log.failed({ error: 'no id' }); throw this.errNoViewReference(); } const coder = new adapty_ui_dialog_config_1.AdaptyUiDialogConfigCoder(); const methodKey = 'adapty_ui_show_dialog'; const body = JSON.stringify({ method: methodKey, id: this.id, configuration: coder.encode(config), }); return yield this.handle(methodKey, body, 'Void', ctx, log); }); } /** * Creates a set of specific view event listeners * * @see {@link https://docs.adapty.io/docs/react-native-handling-events | [DOC] Handling View Events} * * @remarks * It registers only requested set of event handlers. * Your config is assigned into four event listeners {@link DEFAULT_EVENT_HANDLERS}, * that handle default closing behavior. * - `onCloseButtonPress` * - `onAndroidSystemBack` * - `onRestoreCompleted` * - `onPurchaseCompleted` * * If you want to override these listeners, we strongly recommend to return `true` (or `purchaseResult.type !== 'user_cancelled'` in case of `onPurchaseCompleted`) * from your custom listener to retain default closing behavior. * * @param {Partial<EventHandlers> | undefined} [eventHandlers] - set of event handling callbacks * @returns {() => void} unsubscribe - function to unsubscribe all listeners */ registerEventHandlers(eventHandlers = types_1.DEFAULT_EVENT_HANDLERS) { const ctx = new logger_1.LogContext(); const log = ctx.call({ methodName: 'registerEventHandlers' }); log.start({ _id: this.id }); if (this.id === null) { throw this.errNoViewReference(); } const finalEventHandlers = Object.assign(Object.assign({}, types_1.DEFAULT_EVENT_HANDLERS), eventHandlers); // DIY way to tell TS that original arg should not be used const deprecateVar = (_target) => true; if (!deprecateVar(eventHandlers)) { return () => { }; } const viewEmitter = new view_emitter_1.ViewEmitter(this.id); Object.keys(finalEventHandlers).forEach(eventStr => { const event = eventStr; if (!finalEventHandlers.hasOwnProperty(event)) { return; } const handler = finalEventHandlers[event]; viewEmitter.addListener(event, handler, () => this.dismiss()); }); const unsubscribe = () => viewEmitter.removeAllListeners(); // expose to class to be able to unsubscribe on dismiss this.unsubscribeAllListeners = unsubscribe; return unsubscribe; } errNoViewReference() { throw new Error('View reference not found'); } } exports.ViewController = ViewController; //# sourceMappingURL=view-controller.js.map