UNPKG

react-native-adapty

Version:
185 lines 6.85 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.OnboardingViewEmitter = void 0; const bridge_1 = require("../bridge"); const onboarding_events_1 = require("../types/onboarding-events"); const logger_1 = require("../logger"); // Emitting view ID is passed in JSON["_view_id"] // So that no all visible views would emit this event // Must be in every callback response in the form of UUID string // const KEY_VIEW = 'view_id'; /** * OnboardingViewEmitter manages event handlers for onboarding view events. * Each event type can have only one handler - new handlers replace existing ones. * * @remarks * View emitter wraps NativeEventEmitter * and provides several modifications: * - Synthetic type restrictions to avoid misspelling * - Safe data deserialization with SDK decoders * - Logging emitting and deserialization processes * - Filters out events for other views by _id * * @internal */ class OnboardingViewEmitter { constructor(viewId) { this.eventListeners = new Map(); this.handlers = new Map(); this.viewId = viewId; } addListener(event, callback, onRequestClose) { const config = HANDLER_TO_EVENT_CONFIG[event]; if (!config) { throw new Error(`No event config found for handler: ${event}`); } // Replace existing handler for this event type this.handlers.set(event, { handler: callback, config, onRequestClose, }); if (!this.eventListeners.has(config.nativeEvent)) { const subscription = bridge_1.$bridge.addEventListener(config.nativeEvent, this.createEventHandler(config)); this.eventListeners.set(config.nativeEvent, subscription); } return this.eventListeners.get(config.nativeEvent); } createEventHandler(config) { return (parsedEvent) => { const eventViewId = parsedEvent.view.id; if (this.viewId !== eventViewId) { return; } const ctx = new logger_1.LogContext(); const log = ctx.event({ methodName: config.nativeEvent }); log.start({ viewId: eventViewId, eventId: parsedEvent.id }); // Get all possible handler names for this native event const possibleHandlers = NATIVE_EVENT_TO_HANDLERS[config.nativeEvent] || []; let hasError = false; for (const handlerName of possibleHandlers) { const handlerData = this.handlers.get(handlerName); if (!handlerData) { continue; // Handler not registered for this view } const { handler, onRequestClose } = handlerData; const callbackArgs = extractCallbackArgs(handlerName, parsedEvent); const callback = handler; let shouldClose = false; try { shouldClose = callback(...callbackArgs); } catch (error) { hasError = true; shouldClose = true; log.failed({ error, handlerName, viewId: eventViewId, eventId: parsedEvent.id, reason: 'user_handler_failed', }); } if (shouldClose) { onRequestClose().catch(error => { log.failed({ error, handlerName, viewId: eventViewId, eventId: parsedEvent.id, reason: 'on_request_close_failed', }); }); } } if (!hasError) { log.success({ viewId: eventViewId, eventId: parsedEvent.id }); } }; } removeAllListeners() { this.eventListeners.forEach(subscription => subscription.remove()); this.eventListeners.clear(); this.handlers.clear(); } } exports.OnboardingViewEmitter = OnboardingViewEmitter; const ONBOARDING_EVENT_MAPPINGS = { onboarding_on_close_action: [ { handlerName: 'onClose', }, ], onboarding_on_custom_action: [ { handlerName: 'onCustom', }, ], onboarding_on_paywall_action: [ { handlerName: 'onPaywall', }, ], onboarding_on_state_updated_action: [ { handlerName: 'onStateUpdated', }, ], onboarding_did_finish_loading: [ { handlerName: 'onFinishedLoading', }, ], onboarding_on_analytics_action: [ { handlerName: 'onAnalytics', }, ], onboarding_did_fail_with_error: [ { handlerName: 'onError', }, ], }; const HANDLER_TO_EVENT_CONFIG = Object.entries(ONBOARDING_EVENT_MAPPINGS).reduce((acc, [nativeEvent, mappings]) => { mappings.forEach(({ handlerName }) => { acc[handlerName] = { nativeEvent, handlerName, }; }); return acc; }, {}); // Reverse mapping: nativeEvent -> EventName[] const NATIVE_EVENT_TO_HANDLERS = Object.entries(HANDLER_TO_EVENT_CONFIG).reduce((acc, [handlerName, config]) => { if (!acc[config.nativeEvent]) { acc[config.nativeEvent] = []; } const handlers = acc[config.nativeEvent]; if (handlers) { handlers.push(handlerName); } return acc; }, {}); function extractCallbackArgs(_handlerName, event) { switch (event.id) { case onboarding_events_1.OnboardingEventId.Close: case onboarding_events_1.OnboardingEventId.Custom: case onboarding_events_1.OnboardingEventId.Paywall: return [event.actionId, event.meta]; case onboarding_events_1.OnboardingEventId.StateUpdated: return [event.action, event.meta]; case onboarding_events_1.OnboardingEventId.FinishedLoading: return [event.meta]; case onboarding_events_1.OnboardingEventId.Analytics: return [ Object.assign(Object.assign({}, event.event), { // Add backward compatibility: populate element_id from elementId element_id: event.event.elementId }), event.meta, ]; case onboarding_events_1.OnboardingEventId.Error: return [event.error]; } } //# sourceMappingURL=onboarding-view-emitter.js.map