@@ -13,6 +13,7 @@ import {
1313} from '../actions/postActivity' ;
1414import { SENDING , SEND_FAILED , SENT } from '../types/internal/SendStatus' ;
1515import getActivityLivestreamingMetadata from '../utils/getActivityLivestreamingMetadata' ;
16+ import getOrgSchemaMessage from '../utils/getOrgSchemaMessage' ;
1617import findBeforeAfter from './private/findBeforeAfter' ;
1718
1819import type { Reducer } from 'redux' ;
@@ -74,6 +75,10 @@ function patchActivity(
7475 activity = updateIn ( activity , [ 'channelData' ] , channelData => ( { ...channelData } ) ) ;
7576 activity = updateIn ( activity , [ 'channelData' , 'webChat' , 'receivedAt' ] , ( ) => Date . now ( ) ) ;
7677
78+ const messageEntity = getOrgSchemaMessage ( activity . entities ) ;
79+ const entityPosition = messageEntity ?. position ;
80+ const entityPartOf = messageEntity ?. isPartOf ?. [ '@id' ] ;
81+
7782 const {
7883 channelData : { 'webchat:sequence-id' : sequenceId }
7984 } = activity ;
@@ -128,6 +133,13 @@ function patchActivity(
128133 activity = updateIn ( activity , [ 'channelData' , 'webchat:sequence-id' ] , ( ) => sequenceId ) ;
129134 }
130135
136+ if ( typeof entityPosition === 'number' ) {
137+ activity = updateIn ( activity , [ 'channelData' , 'webchat:entity-position' ] , ( ) => entityPosition ) ;
138+ }
139+ if ( typeof entityPartOf === 'string' ) {
140+ activity = updateIn ( activity , [ 'channelData' , 'webchat:entity-part-of' ] , ( ) => entityPartOf ) ;
141+ }
142+
131143 return activity ;
132144}
133145
@@ -165,10 +177,25 @@ function upsertActivityWithSort(
165177 ! ( nextClientActivityID && clientActivityID === nextClientActivityID ) && ! ( id && id === nextActivity . id )
166178 ) ;
167179
168- // Then, find the right (sorted) place to insert the new activity at, based on sequence ID.
169- const indexToInsert = nextActivities . findIndex (
170- ( { channelData : { 'webchat:sequence-id' : sequenceId } = { } } ) => ( sequenceId || 0 ) > ( nextSequenceId || 0 )
171- ) ;
180+ const nextEntityPosition = nextActivity . channelData ?. [ 'webchat:entity-position' ] ;
181+ const nextPartOf = nextActivity . channelData ?. [ 'webchat:entity-part-of' ] ;
182+
183+ const indexToInsert = nextActivities . findIndex ( ( { channelData = { } } ) => {
184+ const currentSequenceId = channelData [ 'webchat:sequence-id' ] || 0 ;
185+ const currentPosition = channelData [ 'webchat:entity-position' ] ;
186+ const currentPartOf = channelData [ 'webchat:entity-part-of' ] ;
187+
188+ const bothHavePosition = typeof currentPosition === 'number' && typeof nextEntityPosition === 'number' ;
189+ const bothArePartOf = typeof currentPartOf === 'string' && currentPartOf === nextPartOf ;
190+
191+ // For activities in the same creative work part, position is primary sort key
192+ if ( bothHavePosition && bothArePartOf ) {
193+ return currentPosition > nextEntityPosition ;
194+ }
195+
196+ // For activities not in the same part or without positions follow sequence ID order
197+ return ( currentSequenceId || 0 ) > ( nextSequenceId || 0 ) ;
198+ } ) ;
172199
173200 // If no right place are found, append it
174201 nextActivities . splice ( ~ indexToInsert ? indexToInsert : nextActivities . length , 0 , nextActivity ) ;
0 commit comments