@@ -6,7 +6,7 @@ import type {
66 SettleObservation ,
77} from '../../contracts/interaction.ts' ;
88import { successText } from '../../utils/success-text.ts' ;
9- import { interactionResultExtra , stripAtPrefix } from './interaction-touch-targets.ts' ;
9+ import { interactionResultExtra } from './interaction-touch-targets.ts' ;
1010
1111/**
1212 * The single construction site for interaction response payloads (ADR 0011
@@ -26,17 +26,12 @@ export type InteractionResponseSource =
2626 | {
2727 kind : 'runtime' ;
2828 result : InteractionRuntimeResult ;
29- /**
30- * Wire-compat for fill @ref: the response echoes backendResult (or a
31- * minimal ref/point fallback) plus the identity extras instead of the
32- * visualization shape. Only applies when the result resolved as a ref.
33- */
34- refBackendWireShape ?: boolean ;
3529 }
3630 | {
3731 // Direct iOS selector dispatch: no runtime result exists, only the raw
3832 // runner payload; identity extras are a declared gap on that path.
3933 kind : 'runner-payload' ;
34+ targetKind : InteractionRuntimeResult [ 'kind' ] ;
4035 data : Record < string , unknown > ;
4136 point : { x : number ; y : number } ;
4237 } ;
@@ -77,39 +72,49 @@ export function buildInteractionResponseData(params: {
7772} ) : InteractionResponsePayloads {
7873 const { source, referenceFrame, extra } = params ;
7974 if ( source . kind === 'runner-payload' ) {
80- const payload = buildTouchVisualizationResult ( {
75+ const commonExtra = {
76+ targetKind : source . targetKind ,
77+ ...( extra ?? { } ) ,
78+ } ;
79+ const result = buildTouchPayload ( {
8180 data : source . data ,
8281 fallbackX : source . point . x ,
8382 fallbackY : source . point . y ,
8483 referenceFrame,
85- extra,
84+ extra : commonExtra ,
85+ } ) ;
86+ const responseData = buildTouchPayload ( {
87+ data : sanitizeWireBackendData ( source . data ) ,
88+ fallbackX : source . point . x ,
89+ fallbackY : source . point . y ,
90+ referenceFrame,
91+ extra : commonExtra ,
8692 } ) ;
87- return { result : payload , responseData : payload } ;
93+ return { result, responseData } ;
8894 }
8995
9096 const { result } = source ;
91- const visualization = buildTouchVisualizationResult ( {
97+ const resultExtra = interactionResultExtra ( result ) ;
98+ const commonExtra = {
99+ targetKind : result . kind ,
100+ ...resultExtra ,
101+ ...settleExtra ( result . settle , params . settleRefsGeneration ) ,
102+ ...( extra ?? { } ) ,
103+ } ;
104+ const visualization = buildTouchPayload ( {
92105 data : result . backendResult ,
93106 fallbackX : result . point ?. x ,
94107 fallbackY : result . point ?. y ,
95108 referenceFrame,
96- extra : {
97- ...interactionResultExtra ( result ) ,
98- ...settleExtra ( result . settle , params . settleRefsGeneration ) ,
99- ...( extra ?? { } ) ,
100- } ,
109+ extra : commonExtra ,
110+ } ) ;
111+ const responseData = buildTouchPayload ( {
112+ data : sanitizeWireBackendData ( result . backendResult ) ,
113+ fallbackX : result . point ?. x ,
114+ fallbackY : result . point ?. y ,
115+ referenceFrame,
116+ extra : commonExtra ,
101117 } ) ;
102- const responseData =
103- source . refBackendWireShape && result . kind === 'ref'
104- ? {
105- ...( result . backendResult ?? {
106- ref : stripAtPrefix ( result . target ?. kind === 'ref' ? result . target . ref : undefined ) ,
107- ...( result . point ? { x : result . point . x , y : result . point . y } : { } ) ,
108- } ) ,
109- ...interactionResultExtra ( result ) ,
110- ...settleExtra ( result . settle , params . settleRefsGeneration ) ,
111- }
112- : visualization ;
113118 const warning = composeResponseWarning (
114119 'warning' in result ? result . warning : undefined ,
115120 params . staleRefsWarning ,
@@ -140,7 +145,7 @@ function composeResponseWarning(
140145 return resultWarning ? `${ resultWarning } ${ staleRefsWarning } ` : staleRefsWarning ;
141146}
142147
143- function buildTouchVisualizationResult ( params : {
148+ function buildTouchPayload ( params : {
144149 data : Record < string , unknown > | undefined ;
145150 fallbackX ?: number ;
146151 fallbackY ?: number ;
@@ -151,40 +156,96 @@ function buildTouchVisualizationResult(params: {
151156 const message =
152157 buildTouchMessage ( extra , fallbackX , fallbackY ) ??
153158 ( typeof data ?. message === 'string' ? data . message : undefined ) ;
154- return {
159+ return stripUndefinedFields ( {
160+ ...( data ?? { } ) ,
155161 ...( fallbackX === undefined || fallbackY === undefined ? { } : { x : fallbackX , y : fallbackY } ) ,
156162 ...( referenceFrame ?? { } ) ,
157163 ...( extra ?? { } ) ,
158- ...( data ?? { } ) ,
159164 ...successText ( message ) ,
160- } ;
165+ } ) ;
166+ }
167+
168+ function stripUndefinedFields ( data : Record < string , unknown > ) : Record < string , unknown > {
169+ return Object . fromEntries ( Object . entries ( data ) . filter ( ( [ , value ] ) => value !== undefined ) ) ;
170+ }
171+
172+ function sanitizeWireBackendData (
173+ data : Record < string , unknown > | undefined ,
174+ ) : Record < string , unknown > | undefined {
175+ if ( ! data ) return undefined ;
176+ const sanitized = Object . fromEntries (
177+ Object . entries ( data ) . filter ( ( [ key , value ] ) => shouldKeepWireBackendField ( key , value ) ) ,
178+ ) ;
179+ return Object . keys ( sanitized ) . length > 0 ? sanitized : undefined ;
180+ }
181+
182+ function shouldKeepWireBackendField ( key : string , value : unknown ) : boolean {
183+ switch ( key ) {
184+ case 'gestureStartUptimeMs' :
185+ case 'gestureEndUptimeMs' :
186+ case 'sequenceResults' :
187+ return false ;
188+ case 'count' :
189+ return value !== 1 ;
190+ case 'intervalMs' :
191+ case 'holdMs' :
192+ case 'jitterPx' :
193+ return value !== 0 ;
194+ case 'doubleTap' :
195+ return value !== false ;
196+ default :
197+ return true ;
198+ }
161199}
162200
163201function buildTouchMessage (
164202 extra : Record < string , unknown > | undefined ,
165203 x : number | undefined ,
166204 y : number | undefined ,
167205) : string | undefined {
168- if ( typeof extra ?. text === 'string' ) {
169- return `Filled ${ Array . from ( extra . text ) . length } chars` ;
170- }
171- const ref = typeof extra ?. ref === 'string' ? extra . ref : undefined ;
172- if ( ! ref ) return undefined ;
173- const pointSuffix = x === undefined || y === undefined ? '' : ` (${ x } , ${ y } )` ;
174- return buildRefTouchMessage ( ref , extra ?? { } , pointSuffix ) ;
206+ const fillText = readString ( extra , 'text' ) ;
207+ if ( fillText !== undefined ) return `Filled ${ Array . from ( fillText ) . length } chars` ;
208+
209+ const pointSuffix = buildPointSuffix ( x , y ) ;
210+ const label = buildTouchTargetLabel ( extra ) ;
211+ if ( label ) return buildTouchTargetMessage ( label , extra ?? { } , pointSuffix ) ;
212+ if ( ! pointSuffix ) return undefined ;
213+
214+ return buildPointTouchMessage ( extra , pointSuffix ) ;
215+ }
216+
217+ function readString ( data : Record < string , unknown > | undefined , key : string ) : string | undefined {
218+ const value = data ?. [ key ] ;
219+ return typeof value === 'string' ? value : undefined ;
220+ }
221+
222+ function buildPointSuffix ( x : number | undefined , y : number | undefined ) : string {
223+ return x === undefined || y === undefined ? '' : ` (${ x } , ${ y } )` ;
224+ }
225+
226+ function buildTouchTargetLabel ( extra : Record < string , unknown > | undefined ) : string | undefined {
227+ const ref = readString ( extra , 'ref' ) ;
228+ return ref === undefined ? readString ( extra , 'selector' ) : `@${ ref } ` ;
229+ }
230+
231+ function buildPointTouchMessage (
232+ extra : Record < string , unknown > | undefined ,
233+ pointSuffix : string ,
234+ ) : string {
235+ return extra ?. gesture === 'longpress' ? `Long pressed${ pointSuffix } ` : `Tapped${ pointSuffix } ` ;
175236}
176237
177- function buildRefTouchMessage (
178- ref : string ,
238+ function buildTouchTargetMessage (
239+ label : string ,
179240 extra : Record < string , unknown > ,
180241 pointSuffix : string ,
181242) : string {
182243 const button = typeof extra . button === 'string' ? extra . button : undefined ;
183244 if ( extra . gesture === 'longpress' ) {
184- return `Long pressed @ ${ ref } ${ pointSuffix } ` ;
245+ return `Long pressed ${ label } ${ pointSuffix } ` ;
185246 }
186247 if ( button && button !== 'primary' ) {
187- return `Clicked ${ button } @ ${ ref } ${ pointSuffix } ` ;
248+ return `Clicked ${ button } ${ label } ${ pointSuffix } ` ;
188249 }
189- return `Tapped @ ${ ref } ${ pointSuffix } ` ;
250+ return `Tapped ${ label } ${ pointSuffix } ` ;
190251}
0 commit comments