import NativeTBLRNTTurboModule from '../NativeTBLRNTTurboModule'; import type { TBLClassicListener } from './TBLClassicListener'; import type { ResizeCallback, RNNativeTBLEvents, } from '@taboola/react-native-plugin-4x'; export class TBLRNClassicUnitEventHandler { private readonly unitId: string; private readonly tblRNClassicListener: RNNativeTBLEvents; private resizeCallback?: ResizeCallback; constructor( unitId: string, tblClassicListener: TBLClassicListener, setTBLClassicUnitControllerHeight: (height: number) => void ) { try { console.log('[TBLSOS] [TBLRNClassicUnitEventHandler.constructor] Entry', { unitId, hasListener: !!tblClassicListener, listenerType: typeof tblClassicListener }); this.unitId = unitId; console.log('[TBLSOS] [TBLRNClassicUnitEventHandler.constructor] About to setup native events'); this.tblRNClassicListener = this.setupNativeEvents( tblClassicListener, setTBLClassicUnitControllerHeight ); console.log('[TBLSOS] [TBLRNClassicUnitEventHandler.constructor] Native events setup completed'); } catch (error) { console.error('[TBLSOS] [TBLRNClassicUnitEventHandler.constructor] ERROR:', error); console.error('[TBLSOS] [TBLRNClassicUnitEventHandler.constructor] Error stack:', error instanceof Error ? error.stack : 'No stack trace'); throw error; } } private shouldSendEventToUnit(unitId: string): boolean { console.log("[TBLSOS] [TBLRNClassicUnitEventHandler] [shouldSendEventToUnit] Comparing event unitId:", unitId, "with handler unitId:", this.unitId, "shouldSendEventToUnit? ", unitId === this.unitId); return unitId === this.unitId; } setupNativeEvents( tblClassicListener: TBLClassicListener, setTBLClassicUnitControllerHeight: (height: number) => void ): RNNativeTBLEvents { try { // Check if NativeTBLRNTTurboModule is properly initialized console.log('[TBLSOS] [setupNativeEvents] NativeTBLRNTTurboModule type:', typeof NativeTBLRNTTurboModule); console.log('[TBLSOS] [setupNativeEvents] NativeTBLRNTTurboModule.onResize type:', typeof NativeTBLRNTTurboModule?.onResize); if (!NativeTBLRNTTurboModule) { throw new Error('NativeTBLRNTTurboModule is not initialized'); } if (typeof NativeTBLRNTTurboModule.onResize !== 'function') { console.error('[TBLSOS] [setupNativeEvents] onResize is not a function:', NativeTBLRNTTurboModule.onResize); throw new Error('TBLSOS NativeTBLRNTTurboModule.onResize is not a function'); } if (typeof NativeTBLRNTTurboModule.onAdReceiveSuccess !== 'function') { console.error('[TBLSOS] [setupNativeEvents] onAdReceiveSuccess is not a function:', NativeTBLRNTTurboModule.onAdReceiveSuccess); throw new Error('TBLSOS NativeTBLRNTTurboModule.onAdReceiveSuccess is not a function'); } if (typeof NativeTBLRNTTurboModule.onAdReceiveFail !== 'function') { console.error('[TBLSOS] [setupNativeEvents] onAdReceiveFail is not a function:', NativeTBLRNTTurboModule.onAdReceiveFail); throw new Error('TBLSOS NativeTBLRNTTurboModule.onAdReceiveFail is not a function'); } console.log('[TBLSOS] [setupNativeEvents] Setting up onResize'); const onResize = NativeTBLRNTTurboModule.onResize((value) => { console.log('[TBLSOS] [setupNativeEvents] Setting up onResize this.resizeCallback ? ', !!this.resizeCallback, "received onResize value:", value); if (!this.resizeCallback) return; if (this.shouldSendEventToUnit(value.unitId)) { setTBLClassicUnitControllerHeight(value.height); tblClassicListener.onResize(value.height); this.resizeCallback({ height: value.height, placement: value.unitId, }); } }); console.log('[TBLSOS] [setupNativeEvents] onResize setup complete, subscription:', onResize); console.log('[TBLSOS] [setupNativeEvents] Setting up onItemClick'); const onItemClick = NativeTBLRNTTurboModule.onItemClick((value) => { if (this.shouldSendEventToUnit(value.unitId)) { tblClassicListener.onItemClick( value.placement, value.itemId, value.clickUrl, value.isOrganic, value.customData ); } }); console.log('[TBLSOS] [setupNativeEvents] onItemClick setup complete'); console.log('[TBLSOS] [setupNativeEvents] Setting up onTaboolaWidgetOnTop'); const onTaboolaWidgetOnTop = NativeTBLRNTTurboModule.onTaboolaWidgetOnTop( (value) => { if (this.shouldSendEventToUnit(value.unitId)) { tblClassicListener.onTaboolaWidgetOnTop(); } } ); console.log('[TBLSOS] [setupNativeEvents] onTaboolaWidgetOnTop setup complete'); console.log('[TBLSOS] [setupNativeEvents] Setting up onAdReceiveSuccess'); const onAdReceiveSuccess = NativeTBLRNTTurboModule.onAdReceiveSuccess( (value) => { if (this.shouldSendEventToUnit(value.unitId)) { tblClassicListener.onAdReceiveSuccess(); } } ); console.log('[TBLSOS] [setupNativeEvents] onAdReceiveSuccess setup complete'); console.log('[TBLSOS] [setupNativeEvents] Setting up onAdReceiveFail'); const onAdReceiveFail = NativeTBLRNTTurboModule.onAdReceiveFail((value) => { if (this.shouldSendEventToUnit(value.unitId)) { tblClassicListener.onAdReceiveFail(value.error); } }); console.log('[TBLSOS] [setupNativeEvents] onAdReceiveFail setup complete'); console.log('[TBLSOS] [setupNativeEvents] Setting up onUpdateContentCompleted'); const onUpdateContentCompleted = NativeTBLRNTTurboModule.onUpdateContentCompleted((value) => { if (this.shouldSendEventToUnit(value.unitId)) { tblClassicListener.onUpdateContentCompleted(); } }); console.log('[TBLSOS] [setupNativeEvents] onUpdateContentCompleted setup complete'); console.log('[TBLSOS] [setupNativeEvents] Setting up onEvent'); const onEvent = NativeTBLRNTTurboModule.onEvent((value) => { if (this.shouldSendEventToUnit(value.unitId)) { tblClassicListener.onEvent(value.actionType, value.data); } }); console.log('[TBLSOS] [setupNativeEvents] onEvent setup complete'); console.log('[TBLSOS] [setupNativeEvents] All events setup successfully'); return { onResize, onItemClick, onTaboolaWidgetOnTop, onAdReceiveSuccess, onAdReceiveFail, onUpdateContentCompleted, onEvent, }; } catch (error) { console.error('[TBLSOS] [setupNativeEvents] ERROR during event setup:', error); throw error; } } /** * Set the resize callback function, this function controller and resizing TBClassicUnit.tsx. * @param resizeCallback */ setResizeCallback(resizeCallback: ResizeCallback) { this.resizeCallback = resizeCallback; } /** * Removes all native event listeners to prevent memory leaks */ cleanListeners(): void { Object.values(this.tblRNClassicListener).forEach((subscription) => { if (subscription && typeof subscription.remove === 'function') { subscription.remove(); } }); this.resizeCallback = undefined; } }