@@ -38,6 +38,11 @@ interface StreamRequestInstance extends PlainRecord {
3838 networkCode : string | null ;
3939 omidAccessModeRules : PlainRecord | null ;
4040 streamActivityMonitorId : string | null ;
41+ ui : StreamRequestUiInstance ;
42+ }
43+
44+ interface StreamRequestUiInstance extends PlainRecord {
45+ custom : PlainRecord | null ;
4146}
4247
4348interface LiveStreamRequestInstance extends StreamRequestInstance {
@@ -102,6 +107,46 @@ interface UiSettingsInstance {
102107 setLocale ( locale : string ) : void ;
103108}
104109
110+ interface UiImageInstance {
111+ altText : string ;
112+ height : number ;
113+ url : string ;
114+ width : number ;
115+ }
116+
117+ interface UiDataInstance extends PlainRecord {
118+ altText ?: string ;
119+ clickable : boolean ;
120+ clickUrl ?: string ;
121+ imageUrl ?: string ;
122+ imageVariants ?: UiImageInstance [ ] ;
123+ required : boolean ;
124+ text ?: string ;
125+ }
126+
127+ interface UiOptionsInstance {
128+ aboutThisAdSupport : boolean ;
129+ clickThroughNavigation : string ;
130+ skippableSupport : boolean ;
131+ }
132+
133+ interface CustomUiOptionsInstance {
134+ aboutThisAdSupport : boolean ;
135+ skippableSupport : boolean ;
136+ }
137+
138+ interface UiDelegateInstance extends PlainRecord {
139+ getConfig ?: ( ) => Map < string , UiDataInstance > ;
140+ onClick ?: ( uiKey : string , eventData ?: unknown ) => void ;
141+ setVisibleElements ?: ( uiElements : unknown ) => void ;
142+ }
143+
144+ interface UiInstance {
145+ getConfig ( ) : Map < string , UiDataInstance > ;
146+ onClick ( uiKey : string , eventData ?: unknown ) : void ;
147+ setVisibleElements ( uiElements : unknown ) : void ;
148+ }
149+
105150interface DaiSdkSettingsInstance {
106151 getFeatureFlags ( ) : PlainRecord ;
107152 setFeatureFlags ( featureFlags : PlainRecord ) : void ;
@@ -189,6 +234,39 @@ type UiSettingsConstructor = {
189234 prototype : UiSettingsInstance ;
190235} ;
191236
237+ type UiImageConstructor = {
238+ new ( uiImage ?: PlainRecord | null ) : UiImageInstance ;
239+ prototype : UiImageInstance ;
240+ } ;
241+
242+ type UiDataConstructor = {
243+ new ( uiData ?: PlainRecord | null ) : UiDataInstance ;
244+ prototype : UiDataInstance ;
245+ UiImage : UiImageConstructor ;
246+ } ;
247+
248+ type UiOptionsConstructor = {
249+ new ( uiOptions ?: PlainRecord | null ) : UiOptionsInstance ;
250+ prototype : UiOptionsInstance ;
251+ ClickThroughNavigation : {
252+ EXTERNAL : 'external' ;
253+ NOT_SUPPORTED : 'notSupported' ;
254+ } ;
255+ } ;
256+
257+ type CustomUiOptionsConstructor = {
258+ new ( uiOptions ?: PlainRecord | null ) : CustomUiOptionsInstance ;
259+ prototype : CustomUiOptionsInstance ;
260+ } ;
261+
262+ type UiConstructor = {
263+ new ( uiDelegate ?: PlainRecord | null ) : UiInstance ;
264+ prototype : UiInstance ;
265+ UiData : UiDataConstructor ;
266+ UiKey : PlainRecord ;
267+ UiOptions : UiOptionsConstructor ;
268+ } ;
269+
192270type DaiSdkSettingsConstructor = {
193271 new ( ) : DaiSdkSettingsInstance ;
194272 prototype : DaiSdkSettingsInstance ;
@@ -279,6 +357,22 @@ export function GoogleIma3Dai(source: Source) {
279357 return typeof value === 'string' && value . length > 0 ? value : null ;
280358 } ;
281359
360+ /**
361+ * Normalizes the stream request UI container.
362+ *
363+ * @param value - The candidate UI container to normalize.
364+ */
365+ const normalizeStreamRequestUi = ( value : unknown ) : StreamRequestUiInstance => {
366+ if ( ! isRecord ( value ) ) {
367+ return { custom : null } ;
368+ }
369+
370+ const normalizedUi = Object . assign ( { custom : null } , value ) ;
371+ normalizedUi . custom = isRecord ( normalizedUi . custom ) ? normalizedUi . custom : null ;
372+
373+ return normalizedUi as StreamRequestUiInstance ;
374+ } ;
375+
282376 /**
283377 * Initializes the listener registry for an event handler instance.
284378 *
@@ -331,11 +425,13 @@ export function GoogleIma3Dai(source: Source) {
331425 instance . networkCode = null ;
332426 instance . omidAccessModeRules = null ;
333427 instance . streamActivityMonitorId = null ;
428+ instance . ui = { custom : null } ;
334429
335430 if ( isRecord ( streamRequest ) ) {
336431 Object . assign ( instance , streamRequest ) ;
337432 }
338433 instance . adTagParameters = toStringRecord ( instance . adTagParameters ) ;
434+ instance . ui = normalizeStreamRequestUi ( instance . ui ) ;
339435
340436 if ( typeof instance . format !== 'string' || instance . format . length === 0 ) {
341437 instance . format = 'hls' ;
@@ -598,7 +694,7 @@ export function GoogleIma3Dai(source: Source) {
598694 * Creates a UI settings container.
599695 */
600696 const UiSettings = function ( this : UiSettingsInstance ) {
601- this . locale = '' ;
697+ this . locale = 'en ' ;
602698 } as unknown as UiSettingsConstructor ;
603699 /**
604700 * Returns the configured locale.
@@ -612,8 +708,151 @@ export function GoogleIma3Dai(source: Source) {
612708 * @param locale - The locale string to store.
613709 */
614710 UiSettings . prototype . setLocale = function ( this : UiSettingsInstance , locale : string ) : void {
615- this . locale = locale ;
711+ if ( typeof locale === 'string' && locale . length > 0 ) {
712+ this . locale = locale ;
713+ }
714+ } ;
715+
716+ const uiKeys = {
717+ ABOUT_THIS_AD_FALLBACK_IMAGE : 'aboutThisAdFallbackImage' ,
718+ ABOUT_THIS_AD_ICON : 'aboutThisAdIcon' ,
719+ AD_TITLE : 'adTitle' ,
720+ ATTRIBUTION : 'attribution' ,
721+ AUTHOR_ICON : 'authorIcon' ,
722+ AUTHOR_TITLE : 'authorTitle' ,
723+ CALL_TO_ACTION : 'callToAction' ,
724+ PRE_SKIP : 'preSkip' ,
725+ SKIP_BUTTON : 'skipButton' ,
726+ VIDEO_OVERLAY : 'videoOverlay' ,
727+ } as const ;
728+
729+ const clickThroughNavigation = {
730+ EXTERNAL : 'external' ,
731+ NOT_SUPPORTED : 'notSupported' ,
732+ } as const ;
733+
734+ /**
735+ * Creates a UI image description.
736+ *
737+ * @param uiImage - Optional image fields to copy onto the instance.
738+ */
739+ const UiImage = function ( this : UiImageInstance , uiImage ?: PlainRecord | null ) {
740+ this . altText = '' ;
741+ this . height = 0 ;
742+ this . url = '' ;
743+ this . width = 0 ;
744+
745+ if ( isRecord ( uiImage ) ) {
746+ Object . assign ( this , uiImage ) ;
747+ }
748+
749+ this . altText = getStringValue ( this . altText ) || '' ;
750+ this . height = typeof this . height === 'number' ? this . height : 0 ;
751+ this . url = getStringValue ( this . url ) || '' ;
752+ this . width = typeof this . width === 'number' ? this . width : 0 ;
753+ } as unknown as UiImageConstructor ;
754+
755+ /**
756+ * Creates a UI element configuration record.
757+ *
758+ * @param uiData - Optional UI data fields to copy onto the instance.
759+ */
760+ const UiData = function ( this : UiDataInstance , uiData ?: PlainRecord | null ) {
761+ this . clickable = false ;
762+ this . required = false ;
763+
764+ if ( isRecord ( uiData ) ) {
765+ Object . assign ( this , uiData ) ;
766+ }
767+
768+ this . clickable = Boolean ( this . clickable ) ;
769+ this . required = Boolean ( this . required ) ;
770+
771+ if ( Array . isArray ( this . imageVariants ) ) {
772+ const imageVariants : UiImageInstance [ ] = [ ] ;
773+
774+ for ( let imageVariantIndex = 0 ; imageVariantIndex < this . imageVariants . length ; imageVariantIndex += 1 ) {
775+ imageVariants . push ( new UiImage ( this . imageVariants [ imageVariantIndex ] as unknown as PlainRecord | null ) ) ;
776+ }
777+
778+ this . imageVariants = imageVariants ;
779+ }
780+ } as unknown as UiDataConstructor ;
781+ UiData . UiImage = UiImage ;
782+
783+ /**
784+ * Creates public DAI UI options.
785+ *
786+ * @param uiOptions - Optional UI option fields to copy onto the instance.
787+ */
788+ const UiOptions = function ( this : UiOptionsInstance , uiOptions ?: PlainRecord | null ) {
789+ this . aboutThisAdSupport = false ;
790+ this . clickThroughNavigation = clickThroughNavigation . NOT_SUPPORTED ;
791+ this . skippableSupport = false ;
792+
793+ if ( isRecord ( uiOptions ) ) {
794+ Object . assign ( this , uiOptions ) ;
795+ }
796+
797+ this . aboutThisAdSupport = Boolean ( this . aboutThisAdSupport ) ;
798+ this . clickThroughNavigation = this . clickThroughNavigation === clickThroughNavigation . EXTERNAL
799+ ? clickThroughNavigation . EXTERNAL
800+ : clickThroughNavigation . NOT_SUPPORTED ;
801+ this . skippableSupport = Boolean ( this . skippableSupport ) ;
802+ } as unknown as UiOptionsConstructor ;
803+ UiOptions . ClickThroughNavigation = clickThroughNavigation ;
804+
805+ /**
806+ * Creates custom UI options stored on stream requests.
807+ *
808+ * @param uiOptions - Optional UI option fields to copy onto the instance.
809+ */
810+ const CustomUiOptions = function ( this : CustomUiOptionsInstance , uiOptions ?: PlainRecord | null ) {
811+ this . aboutThisAdSupport = false ;
812+ this . skippableSupport = false ;
813+
814+ if ( isRecord ( uiOptions ) ) {
815+ Object . assign ( this , uiOptions ) ;
816+ }
817+
818+ this . aboutThisAdSupport = Boolean ( this . aboutThisAdSupport ) ;
819+ this . skippableSupport = Boolean ( this . skippableSupport ) ;
820+ } as unknown as CustomUiOptionsConstructor ;
821+
822+ const uiDelegates = new WeakMap < UiInstance , UiDelegateInstance > ( ) ;
823+ /**
824+ * Creates the public `google.ima.dai.api.ui` wrapper.
825+ *
826+ * @param uiDelegate - Optional delegate used to back the wrapper methods.
827+ */
828+ const Ui = function ( this : UiInstance , uiDelegate ?: PlainRecord | null ) {
829+ uiDelegates . set ( this , isRecord ( uiDelegate ) ? uiDelegate as UiDelegateInstance : { } ) ;
830+ } as unknown as UiConstructor ;
831+ Ui . prototype . onClick = function ( this : UiInstance , uiKey : string , eventData ?: unknown ) : void {
832+ const uiDelegate = uiDelegates . get ( this ) ;
833+ if ( uiDelegate && typeof uiDelegate . onClick === 'function' ) {
834+ uiDelegate . onClick ( uiKey , eventData ) ;
835+ }
836+ } ;
837+ Ui . prototype . setVisibleElements = function ( this : UiInstance , uiElements : unknown ) : void {
838+ const uiDelegate = uiDelegates . get ( this ) ;
839+ if ( uiDelegate && typeof uiDelegate . setVisibleElements === 'function' ) {
840+ uiDelegate . setVisibleElements ( uiElements ) ;
841+ }
842+ } ;
843+ Ui . prototype . getConfig = function ( this : UiInstance ) : Map < string , UiDataInstance > {
844+ const uiDelegate = uiDelegates . get ( this ) ;
845+ if ( ! uiDelegate || typeof uiDelegate . getConfig !== 'function' ) {
846+ return new Map ( ) ;
847+ }
848+
849+ const uiConfig = uiDelegate . getConfig ( ) ;
850+
851+ return uiConfig instanceof Map ? uiConfig : new Map ( ) ;
616852 } ;
853+ Ui . UiData = UiData ;
854+ Ui . UiKey = uiKeys ;
855+ Ui . UiOptions = UiOptions ;
617856
618857 const daiSdkFeatureFlagsStorage = new WeakMap < DaiSdkSettingsInstance , PlainRecord > ( ) ;
619858 /**
@@ -1429,13 +1668,17 @@ export function GoogleIma3Dai(source: Source) {
14291668 } as unknown as StreamManagerInstance [ 'streamTimeForContentTime' ] ;
14301669
14311670 const api : PlainRecord = {
1671+ customUi : {
1672+ UiOptions : CustomUiOptions ,
1673+ } ,
14321674 DaiSdkSettings : new DaiSdkSettingsContainer ( ) ,
14331675 LiveStreamRequest,
14341676 PodStreamRequest,
14351677 StreamData,
14361678 StreamEvent,
14371679 StreamManager,
14381680 StreamRequest,
1681+ ui : Ui ,
14391682 UiSettings,
14401683 VideoStitcherLiveStreamRequest,
14411684 VideoStitcherVodStreamRequest,
0 commit comments