import NativeTBLRNTTurboModule from '../NativeTBLRNTTurboModule'; import { type ResizeCallback, type TBLExtraProperties, TBLPlacementType, } from '../types'; import TemplateJS from './TemplateJS'; import { TBLRNClassicUnitEventHandler } from './TBLRNClassicUnitEventHandler'; import type { TBLClassicListener } from './TBLClassicListener'; import { isValid } from '../utils/TBLValidationUtils'; import { Platform } from 'react-native'; import { PLATFORMS } from '../consts'; /** * TBLClassicUnitController manages the lifecycle and interactions * of a Taboola content unit within a React Native application. * * @class * @description * This controller handles: * - Unit initialization * - Event listener management * - Content fetching and refreshing * - Resize and interaction tracking * * Key Responsibilities: * - Manage native Taboola SDK unit interactions * - Handle event subscriptions for resize, clicks, and content updates * - Provide methods for unit manipulation (fetch, reset, refresh) */ class TBLClassicUnitController { public unitId?: string; public pageId: string; public height: number = 0; public placement: string; public templateJS?: TemplateJS; private mode: string; private placementType: TBLPlacementType; private tblRNClassicUnitEventHandler?: TBLRNClassicUnitEventHandler; private tblClassicListener: TBLClassicListener; constructor( pageId: string, placement: string, mode: string, placementType: TBLPlacementType, tblClassicListener: TBLClassicListener ) { this.pageId = pageId; this.placement = placement; this.mode = mode; this.placementType = placementType; this.tblClassicListener = tblClassicListener; } /** * Sets whether Taboola should handle organic clicks * @param shouldHandleOrganicClicks */ setShouldHandleOrganicClicks(shouldHandleOrganicClicks: boolean): void { if (isValid(this.pageId, this.unitId)) { NativeTBLRNTTurboModule.setShouldHandleOrganicClicks( this.pageId, this.unitId!, shouldHandleOrganicClicks ); } } /** * Fetches content for the current unit */ fetchContent() { console.log(`[TBLSOS] [TBLClassicUnitController.fetchContent] Entry unitId ${this.unitId} page ${this.pageId}` ); if (isValid(this.pageId, this.unitId)) { NativeTBLRNTTurboModule.fetchContent(this.pageId, this.unitId!); } else { console.error( '[TBLClassicUnitController] Invalid arguments for fetchContent' ); } } /** * Resets the content unit to its initial state */ reset() { if (isValid(this.pageId, this.unitId)) { NativeTBLRNTTurboModule.resetUnit(this.pageId, this.unitId!); } else { console.error('[TBLClassicUnitController] Invalid arguments for reset'); } } setUserId(userId: string) { if (isValid(this.pageId, this.unitId, userId)) { NativeTBLRNTTurboModule.setUnitUserId(this.pageId, this.unitId!, userId); } else { console.error( '[TBLClassicUnitController] Invalid arguments for setUserId' ); } } setTag(tag: string) { if (isValid(this.pageId, this.unitId, tag)) { NativeTBLRNTTurboModule.setTag(this.pageId, this.unitId!, tag); } else { console.error('[TBLClassicUnitController] Invalid arguments for setTag'); } } setPageId(pageId: string) { if (isValid(this.pageId, this.unitId, pageId)) { NativeTBLRNTTurboModule.setPageIdFromUnit( this.pageId, this.unitId!, pageId ); } else { console.error( '[TBLClassicUnitController] Invalid arguments for setPageId' ); } } setTargetType(targetType: string) { if (Platform.OS === PLATFORMS.ANDROID) { if (isValid(this.pageId, this.unitId, targetType)) { NativeTBLRNTTurboModule.setUnitTargetType( this.pageId, this.unitId!, targetType ); } else { console.error( '[TBLClassicUnitController] Invalid arguments for setTargetType' ); } } else { console.warn( '[TBLClassicUnitController] setTargetType is only supported on Android' ); } } /** * Sets the publisher name for the unit (Android only) * @param publisherName - The publisher name to set */ setPublisherName(publisherName: string) { if (Platform.OS === PLATFORMS.ANDROID) { if (isValid(this.pageId, this.unitId, publisherName)) { NativeTBLRNTTurboModule.setPublisherName( this.pageId, this.unitId!, publisherName ); } else { console.error( '[TBLClassicUnitController] Invalid arguments for setPublisherName' ); } } else { console.warn( '[TBLClassicUnitController] setPublisherName is only supported on Android' ); } } /** * Sets the page type for the unit (Android only) * @param pageType - The page type to set */ setPageType(pageType: string) { if (Platform.OS === PLATFORMS.ANDROID) { if (isValid(this.pageId, this.unitId, pageType)) { NativeTBLRNTTurboModule.setUnitPageType( this.pageId, this.unitId!, pageType ); } else { console.error( '[TBLClassicUnitController] Invalid arguments for setPageType' ); } } else { console.warn( '[TBLClassicUnitController] setPageType is only supported on Android' ); } } /** * Sets the page URL for the unit (Android only) * @param pageUrl - The page URL to set */ setPageUrl(pageUrl: string) { if (Platform.OS === PLATFORMS.ANDROID) { if (isValid(this.pageId, this.unitId, pageUrl)) { NativeTBLRNTTurboModule.setUnitPageUrl( this.pageId, this.unitId!, pageUrl ); } else { console.error( '[TBLClassicUnitController] Invalid arguments for setPageUrl' ); } } else { console.warn( '[TBLClassicUnitController] setPageUrl is only supported on Android' ); } } setUnitExtraProperties(unitExtraProperties: TBLExtraProperties) { if (isValid(this.pageId, this.unitId, unitExtraProperties)) { NativeTBLRNTTurboModule.setUnitExtraProperties( this.pageId, this.unitId!, unitExtraProperties ); } else { console.error( '[TBLClassicUnitController] Invalid arguments for setUnitExtraProperties' ); } } refresh() { if (isValid(this.pageId, this.unitId)) { NativeTBLRNTTurboModule.refreshUnit(this.pageId, this.unitId!); } else { console.error('[TBLClassicUnitController] Invalid arguments for refresh'); } } updateContent() { if (isValid(this.pageId, this.unitId)) { NativeTBLRNTTurboModule.updateContent(this.pageId, this.unitId!); } else { console.error( '[TBLClassicUnitController] Invalid arguments for updateContent' ); } } /** * Clears the unit, removing listeners and resetting state * Useful for component unmounting and cleanup */ clear() { this.tblRNClassicUnitEventHandler?.cleanListeners(); if (isValid(this.pageId, this.unitId)) { NativeTBLRNTTurboModule.clearUnit(this.pageId, this.unitId!); } else { console.error('[TBLClassicUnitController] Invalid arguments for clear'); } } /** * Sets the callback function that will be triggered when resize events occur. * This callback will receive resize event data including height changes. * * @param callback The function to call when resize events occur */ setResizeListener(callback: ResizeCallback) { this.tblRNClassicUnitEventHandler?.setResizeCallback(callback); } async initialize() { try { console.log('[TBLSOS] [TBLClassicUnitController.initialize] Entry', { pageId: this.pageId, placement: this.placement, mode: this.mode, placementType: this.placementType, hasListener: !!this.tblClassicListener, listenerMethods: this.tblClassicListener ? Object.keys(this.tblClassicListener) : [] }); console.log( '[TBLSOS] [TBLClassicUnitController.initialize] Calling NativeTBLRNTTurboModule.build' ); this.unitId = await NativeTBLRNTTurboModule.build( this.pageId, this.placement, this.mode, this.placementType ); console.log( '[TBLSOS] [TBLClassicUnitController.initialize] Native build returned', { unitId: this.unitId, isUnitIdNull: this.unitId === null || this.unitId === undefined, } ); this.templateJS = new TemplateJS(this.pageId, this.unitId); console.log( '[TBLSOS] [TBLClassicUnitController.initialize] TemplateJS created' ); console.log( '[TBLSOS] [TBLClassicUnitController.initialize] About to create event handler' ); console.log( `[TBLSOS] [TBLClassicUnitController.initialize] tblClassicListener keys ${Object.keys(this.tblClassicListener)}` ); this.tblRNClassicUnitEventHandler = new TBLRNClassicUnitEventHandler( this.unitId, this.tblClassicListener, (height) => (this.height = height) ); console.log( '[TBLSOS] [TBLClassicUnitController.initialize] Event handler created' ); console.log( '[TBLSOS] [TBLClassicUnitController.initialize] Returning controller', { unitId: this.unitId, pageId: this.pageId, } ); return this; } catch (error) { console.error('[TBLSOS] [TBLClassicUnitController.initialize] ERROR occurred:', error); console.error('[TBLSOS] [TBLClassicUnitController.initialize] Error stack:', error instanceof Error ? error.stack : 'No stack trace'); throw error; } } } export default TBLClassicUnitController;