anear-js-api 0.4.31 → 0.4.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.test +2 -2
- package/lib/state_machines/AnearCoreServiceMachine.js +12 -9
- package/lib/state_machines/AnearEventMachine.js +134 -22
- package/lib/utils/Constants.js +5 -1
- package/lib/utils/DisplayEventProcessor.js +46 -37
- package/lib/utils/MetaProcessing.js +27 -24
- package/package.json +1 -1
package/.env.test
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# connects with the machtest developer account
|
|
2
|
-
ANEARAPP_API_KEY=
|
|
2
|
+
ANEARAPP_API_KEY=abacdeaiefibiefieghtereijief
|
|
3
3
|
ANEARAPP_API_VERSION=v1
|
|
4
|
-
ANEARAPP_APP_ID=
|
|
4
|
+
ANEARAPP_APP_ID=e6da7818-4825d43f7-8979-e1ad6977a8c2
|
|
5
5
|
ANEARAPP_LOGGER_FILE=logs/development.log
|
|
6
6
|
ANEARAPP_LOGGER_LEVEL=debug
|
|
7
7
|
ANEARAPP_ABLY_LOG_LEVEL=2
|
|
@@ -129,7 +129,9 @@ const AnearCoreServiceMachineConfig = appId => ({
|
|
|
129
129
|
actions: ['startNewEventMachine']
|
|
130
130
|
},
|
|
131
131
|
EVENT_MACHINE_EXIT: {
|
|
132
|
-
actions: [
|
|
132
|
+
actions: [
|
|
133
|
+
'cleanupEventMachine'
|
|
134
|
+
]
|
|
133
135
|
}
|
|
134
136
|
}
|
|
135
137
|
},
|
|
@@ -161,9 +163,6 @@ const AnearCoreServiceMachineFunctions = {
|
|
|
161
163
|
return uploader.uploadCss()
|
|
162
164
|
}
|
|
163
165
|
},
|
|
164
|
-
delays: {
|
|
165
|
-
retry_with_backoff_delay: (context, event) => context.retryDelay
|
|
166
|
-
},
|
|
167
166
|
actions: {
|
|
168
167
|
updateContextWithMachineRef: assign(
|
|
169
168
|
{
|
|
@@ -228,14 +227,18 @@ const AnearCoreServiceMachineFunctions = {
|
|
|
228
227
|
}
|
|
229
228
|
}
|
|
230
229
|
),
|
|
231
|
-
cleanupEventMachine: assign({
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
230
|
+
cleanupEventMachine: assign((context, event) => {
|
|
231
|
+
const { [event.eventId]: dropped, ...remaining } = context.anearEventMachines
|
|
232
|
+
logger.debug(`ACSM ${event.eventId} is ${dropped ? "done → cleaning up" : "NOT FOUND"}`)
|
|
233
|
+
|
|
234
|
+
return {
|
|
235
|
+
anearEventMachines: remaining
|
|
236
236
|
}
|
|
237
237
|
})
|
|
238
238
|
},
|
|
239
|
+
delays: {
|
|
240
|
+
retry_with_backoff_delay: (context, event) => context.retryDelay
|
|
241
|
+
},
|
|
239
242
|
guards: {
|
|
240
243
|
noImageAssetFilesFound: (_, event) => event.data === null
|
|
241
244
|
}
|
|
@@ -63,6 +63,8 @@ const AnearEventMachineContext = (
|
|
|
63
63
|
}
|
|
64
64
|
)
|
|
65
65
|
|
|
66
|
+
const MinuteMsecs = minutes => minutes * (60 * 1000)
|
|
67
|
+
|
|
66
68
|
const DeferredStates = [
|
|
67
69
|
// do not process these if they arrive during an unresolved
|
|
68
70
|
// invoke Promise service
|
|
@@ -181,12 +183,18 @@ const ActiveEventStatesConfig = {
|
|
|
181
183
|
],
|
|
182
184
|
on: {
|
|
183
185
|
RENDER_DISPLAY: {
|
|
184
|
-
target: '
|
|
186
|
+
target: '#createdRendering'
|
|
185
187
|
}
|
|
186
188
|
},
|
|
187
189
|
states: {
|
|
188
190
|
waitingAnnounce: {
|
|
189
191
|
id: 'waitingAnnounce',
|
|
192
|
+
after: {
|
|
193
|
+
timeoutEventAnnounce: {
|
|
194
|
+
actions: context => logger.info(`Event ${context.anearEvent.id} TIMED OUT waiting for ANNOUNCE`),
|
|
195
|
+
target: '#canceled'
|
|
196
|
+
}
|
|
197
|
+
},
|
|
190
198
|
on: {
|
|
191
199
|
ANNOUNCE: {
|
|
192
200
|
target: '#activeEvent.announce'
|
|
@@ -196,7 +204,8 @@ const ActiveEventStatesConfig = {
|
|
|
196
204
|
}
|
|
197
205
|
}
|
|
198
206
|
},
|
|
199
|
-
|
|
207
|
+
createdRendering: {
|
|
208
|
+
id: 'createdRendering',
|
|
200
209
|
deferred: DeferredStatesPlus('ANNOUNCE', 'START'),
|
|
201
210
|
invoke: {
|
|
202
211
|
src: 'renderDisplay',
|
|
@@ -220,7 +229,7 @@ const ActiveEventStatesConfig = {
|
|
|
220
229
|
initial: 'transitioning',
|
|
221
230
|
on: {
|
|
222
231
|
RENDER_DISPLAY: {
|
|
223
|
-
target: '
|
|
232
|
+
target: '#announceRendering'
|
|
224
233
|
},
|
|
225
234
|
PARTICIPANT_LEAVE: {
|
|
226
235
|
// creator browser refresh or MIA. Send disconnect events
|
|
@@ -231,19 +240,15 @@ const ActiveEventStatesConfig = {
|
|
|
231
240
|
// a participant could re-entering the event after above PARTICIPANT_LEAVE (browser refresh).
|
|
232
241
|
// so look for existing participants and send reconnect events to interested machines
|
|
233
242
|
cond: 'participantExists',
|
|
234
|
-
actions: 'sendParticipantReconnectEvents'
|
|
235
|
-
target: '#waitingToStart',
|
|
236
|
-
internal: true
|
|
243
|
+
actions: 'sendParticipantReconnectEvents'
|
|
237
244
|
},
|
|
238
245
|
{
|
|
239
246
|
// spectator clicked JOIN
|
|
240
|
-
target: '#
|
|
247
|
+
target: '#newParticipantJoining'
|
|
241
248
|
}
|
|
242
249
|
],
|
|
243
250
|
SPECTATOR_ENTER: {
|
|
244
|
-
actions: 'sendSpectatorEnterToAppEventMachine'
|
|
245
|
-
target: '#waitingToStart',
|
|
246
|
-
internal: true
|
|
251
|
+
actions: 'sendSpectatorEnterToAppEventMachine'
|
|
247
252
|
}
|
|
248
253
|
},
|
|
249
254
|
states: {
|
|
@@ -266,13 +271,20 @@ const ActiveEventStatesConfig = {
|
|
|
266
271
|
waitingToStart: {
|
|
267
272
|
id: 'waitingToStart',
|
|
268
273
|
entry: (c, e) => logger.debug("announce state...waiting for event START"),
|
|
274
|
+
after: {
|
|
275
|
+
timeoutEventStart: {
|
|
276
|
+
actions: context => logger.info(`Event ${context.anearEvent.id} TIMED OUT waiting for START`),
|
|
277
|
+
target: '#canceled'
|
|
278
|
+
}
|
|
279
|
+
},
|
|
269
280
|
on: {
|
|
270
281
|
START: {
|
|
271
282
|
target: '#activeEvent.live'
|
|
272
283
|
}
|
|
273
284
|
}
|
|
274
285
|
},
|
|
275
|
-
|
|
286
|
+
announceRendering: {
|
|
287
|
+
id: 'announceRendering',
|
|
276
288
|
deferred: DeferredStatesPlus('START'),
|
|
277
289
|
invoke: {
|
|
278
290
|
src: 'renderDisplay',
|
|
@@ -285,30 +297,56 @@ const ActiveEventStatesConfig = {
|
|
|
285
297
|
}
|
|
286
298
|
}
|
|
287
299
|
},
|
|
288
|
-
|
|
300
|
+
newParticipantJoining: {
|
|
289
301
|
// a PARTICIPANT_ENTER received from a new user JOIN click. create an AnearParticipantMachine instance.
|
|
290
302
|
// This machine tracks presence, geo-location (when approved by mobile participant),
|
|
291
303
|
// manages active/idle state for long-running events, and manages any ACTION timeouts.
|
|
292
|
-
id: '
|
|
304
|
+
id: 'newParticipantJoining',
|
|
293
305
|
deferred: DeferredStatesPlus('START'),
|
|
294
306
|
invoke: {
|
|
295
307
|
src: 'fetchParticipantData',
|
|
296
308
|
onDone: {
|
|
297
|
-
actions: [
|
|
298
|
-
|
|
299
|
-
'sendParticipantEnterToAppEventMachine'
|
|
300
|
-
],
|
|
301
|
-
target: '#waitingToStart',
|
|
309
|
+
actions: ['startNewParticipantMachine'],
|
|
310
|
+
target: '#waitParticipantReady'
|
|
302
311
|
},
|
|
303
312
|
onError: {
|
|
304
313
|
target: '#activeEvent.failure'
|
|
305
314
|
}
|
|
306
315
|
}
|
|
316
|
+
},
|
|
317
|
+
waitParticipantReady: {
|
|
318
|
+
id: 'waitParticipantReady',
|
|
319
|
+
deferred: DeferredStatesPlus('START'),
|
|
320
|
+
on: {
|
|
321
|
+
PARTICIPANT_MACHINE_READY: {
|
|
322
|
+
actions: ['sendParticipantEnterToAppEventMachine'],
|
|
323
|
+
target: '#waitingToStart',
|
|
324
|
+
internal: true
|
|
325
|
+
}
|
|
326
|
+
}
|
|
307
327
|
}
|
|
308
328
|
}
|
|
309
329
|
},
|
|
310
330
|
live: {
|
|
311
331
|
initial: 'transitioning',
|
|
332
|
+
on: {
|
|
333
|
+
RENDER_DISPLAY: {
|
|
334
|
+
target: '#liveRendering'
|
|
335
|
+
},
|
|
336
|
+
SPECTATOR_ENTER: {
|
|
337
|
+
actions: 'sendSpectatorEnterToAppEventMachine'
|
|
338
|
+
},
|
|
339
|
+
PARTICIPANT_LEAVE: {
|
|
340
|
+
// mid-event browser refresh or MIA. Send disconnect events
|
|
341
|
+
actions: ['sendParticipantDisconnectEvents']
|
|
342
|
+
},
|
|
343
|
+
PARTICIPANT_TIMEOUT: {
|
|
344
|
+
// TBD: A participant(s) who was required to take a click action has
|
|
345
|
+
// failed to do so
|
|
346
|
+
},
|
|
347
|
+
PAUSE: '#activeEvent.paused', // Currently no use-case for these
|
|
348
|
+
CLOSE: '#activeEvent.closed'
|
|
349
|
+
},
|
|
312
350
|
states: {
|
|
313
351
|
transitioning: {
|
|
314
352
|
deferred: DeferredStates,
|
|
@@ -325,8 +363,72 @@ const ActiveEventStatesConfig = {
|
|
|
325
363
|
waitingForActions: {
|
|
326
364
|
id: 'waitingForActions',
|
|
327
365
|
on: {
|
|
328
|
-
|
|
329
|
-
|
|
366
|
+
PARTICIPANT_ENTER: [
|
|
367
|
+
{
|
|
368
|
+
// a participant could re-entering the event after above PARTICIPANT_LEAVE (browser refresh).
|
|
369
|
+
// so look for existing participants and send reconnect events to interested machines
|
|
370
|
+
cond: 'participantExists',
|
|
371
|
+
actions: 'sendParticipantReconnectEvents'
|
|
372
|
+
},
|
|
373
|
+
{
|
|
374
|
+
// in the future, open house events allow spectators to join and leave freely
|
|
375
|
+
// during live.waitingForActions
|
|
376
|
+
cond: 'isOpenHouseEvent',
|
|
377
|
+
target: 'participantEntering'
|
|
378
|
+
},
|
|
379
|
+
{
|
|
380
|
+
// shouldn't receive these so log it and return to current state
|
|
381
|
+
actions: [(c, e) => logger.info("Error: Unexepected PARTICIPANT_ENTER")],
|
|
382
|
+
target: '#activeEvent.failure'
|
|
383
|
+
}
|
|
384
|
+
],
|
|
385
|
+
ACTION: {
|
|
386
|
+
// A participant has clicked an anear-data-action
|
|
387
|
+
actions: ['processParticipantAction']
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
},
|
|
391
|
+
liveRendering: {
|
|
392
|
+
id: 'liveRendering',
|
|
393
|
+
deferred: DeferredStates,
|
|
394
|
+
invoke: {
|
|
395
|
+
src: 'renderDisplay',
|
|
396
|
+
onDone: {
|
|
397
|
+
target: '#waitingForActions',
|
|
398
|
+
internal: true
|
|
399
|
+
},
|
|
400
|
+
onError: {
|
|
401
|
+
target: '#activeEvent.failure'
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
},
|
|
405
|
+
participantEntering: {
|
|
406
|
+
// a PARTICIPANT_ENTER received from a new user JOIN click. Unless already exists,
|
|
407
|
+
// create an AnearParticipantMachine instance.
|
|
408
|
+
// This machine tracks presence, geo-location (when approved by mobile participant),
|
|
409
|
+
// manages active/idle state for long-running events, and manages any ACTION timeouts.
|
|
410
|
+
id: 'participantEntering',
|
|
411
|
+
deferred: DeferredStates,
|
|
412
|
+
invoke: {
|
|
413
|
+
src: 'fetchParticipantData',
|
|
414
|
+
onDone: {
|
|
415
|
+
actions: ['startNewParticipantMachine'],
|
|
416
|
+
target: '#waitParticipantJoined',
|
|
417
|
+
},
|
|
418
|
+
onError: {
|
|
419
|
+
target: '#activeEvent.failure'
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
},
|
|
423
|
+
waitParticipantJoined: {
|
|
424
|
+
id: 'waitParticipantJoined',
|
|
425
|
+
deferred: DeferredStates,
|
|
426
|
+
on: {
|
|
427
|
+
PARTICIPANT_MACHINE_READY: {
|
|
428
|
+
actions: ['sendParticipantEnterToAppEventMachine'],
|
|
429
|
+
target: '#waitingForActions',
|
|
430
|
+
internal: true
|
|
431
|
+
}
|
|
330
432
|
}
|
|
331
433
|
}
|
|
332
434
|
}
|
|
@@ -685,6 +787,9 @@ const AnearEventMachineFunctions = ({
|
|
|
685
787
|
sendParticipantEnterToAppEventMachine: (context, event) => {
|
|
686
788
|
const { anearParticipant } = event.data
|
|
687
789
|
const participantInfo = context.participants[anearParticipant.id]
|
|
790
|
+
|
|
791
|
+
logger.debug(`Participant machine ${participantInfo.id} is READY`)
|
|
792
|
+
|
|
688
793
|
const startEvent = { participant: participantInfo }
|
|
689
794
|
|
|
690
795
|
context.appEventMachine.send('PARTICIPANT_ENTER', startEvent)
|
|
@@ -786,7 +891,7 @@ const AnearEventMachineFunctions = ({
|
|
|
786
891
|
}
|
|
787
892
|
}),
|
|
788
893
|
notifyCoreServiceMachineExit: context => {
|
|
789
|
-
logger.debug("sending EVENT_MACHINE_EXIT to
|
|
894
|
+
logger.debug("sending EVENT_MACHINE_EXIT to coreServiceMachine")
|
|
790
895
|
context.coreServiceMachine.send('EVENT_MACHINE_EXIT', {eventId: context.anearEvent.id})
|
|
791
896
|
}
|
|
792
897
|
},
|
|
@@ -860,7 +965,14 @@ const AnearEventMachineFunctions = ({
|
|
|
860
965
|
},
|
|
861
966
|
guards: {
|
|
862
967
|
participantExists: (context, event) => !!context.participants[event.data.id],
|
|
863
|
-
eventCreatorIsHost: (context, event) => context.anearEvent.hosted
|
|
968
|
+
eventCreatorIsHost: (context, event) => context.anearEvent.hosted,
|
|
969
|
+
isOpenHouseEvent: (context, event) => false // TODO: need to have App open_house trait exposed in anear api
|
|
970
|
+
},
|
|
971
|
+
delays: {
|
|
972
|
+
// in the future, these delays should be goverened by the type of App and
|
|
973
|
+
// if there has been activity.
|
|
974
|
+
timeoutEventAnnounce: context => MinuteMsecs(C.TIMEOUT_MINUTES.ANNOUNCE),
|
|
975
|
+
timeoutEventStart: context => MinuteMsecs(C.TIMEOUT_MINUTES.START)
|
|
864
976
|
}
|
|
865
977
|
})
|
|
866
978
|
|
package/lib/utils/Constants.js
CHANGED
|
@@ -4,15 +4,17 @@
|
|
|
4
4
|
* Pug templates receive the following context at render:
|
|
5
5
|
*
|
|
6
6
|
* {
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
7
|
+
* app: application XState context
|
|
8
|
+
* meta: {
|
|
9
|
+
* viewer: // 'participant', 'participants', 'spectators'
|
|
10
|
+
* state: // Stringified state name (e.g., 'live.registration.waitForOpponentToJoin')
|
|
11
|
+
* event: // The triggering event for this transition ('PARTICIPANT_ENTER')
|
|
12
|
+
* timeout: // null|| { msecs:, [participantId:]}
|
|
13
|
+
* }
|
|
12
14
|
*
|
|
13
15
|
* // When 'participant' displayType
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
+
* participants: // all: Map of all participants [info, context] for this event, get(id) => info, context
|
|
17
|
+
* participant: // info, context
|
|
16
18
|
*
|
|
17
19
|
* // PLUS all helpers from PugHelpers:
|
|
18
20
|
* cdnImg(filename) // Resolves CDN image path
|
|
@@ -37,18 +39,28 @@ class DisplayEventProcessor {
|
|
|
37
39
|
constructor(anearEventMachineContext) {
|
|
38
40
|
this.pugTemplates = anearEventMachineContext.pugTemplates
|
|
39
41
|
this.pugHelpers = anearEventMachineContext.pugHelpers
|
|
40
|
-
this.participants = anearEventMachineContext.participants
|
|
41
42
|
this.participantMachines = anearEventMachineContext.participantMachines
|
|
42
43
|
this.participantsDisplayChannel = anearEventMachineContext.participantsDisplayChannel
|
|
43
44
|
this.spectatorsDisplayChannel = anearEventMachineContext.spectatorsDisplayChannel
|
|
45
|
+
this.participantsIndex = this._buildParticipantsIndex(anearEventMachineContext.participants)
|
|
44
46
|
}
|
|
45
47
|
|
|
46
48
|
processAndPublish(displayEvents) {
|
|
47
49
|
return Promise.all(displayEvents.map(event => this._processSingle(event)))
|
|
48
50
|
}
|
|
49
51
|
|
|
52
|
+
_buildParticipantsIndex(participants) {
|
|
53
|
+
const participantStructs = Object.fromEntries(
|
|
54
|
+
Object.entries(participants).map(([id, info]) => [ id, { info, context: null } ])
|
|
55
|
+
)
|
|
56
|
+
const all = Object.values(participantStructs)
|
|
57
|
+
|
|
58
|
+
return { all, get: id => participantStructs[id] }
|
|
59
|
+
}
|
|
60
|
+
|
|
50
61
|
_processSingle(displayEvent) {
|
|
51
|
-
const {
|
|
62
|
+
const { viewPath, appRenderContext } = displayEvent
|
|
63
|
+
const timeout = appRenderContext.meta.timeout
|
|
52
64
|
|
|
53
65
|
const normalizedPath = viewPath.endsWith(C.PugSuffix) ? viewPath : `${viewPath}${C.PugSuffix}`
|
|
54
66
|
const template = this.pugTemplates[normalizedPath]
|
|
@@ -57,61 +69,58 @@ class DisplayEventProcessor {
|
|
|
57
69
|
throw new Error(`Template not found: ${normalizedPath}`)
|
|
58
70
|
}
|
|
59
71
|
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
participants: this.participants,
|
|
72
|
+
const templateRenderContext = {
|
|
73
|
+
...appRenderContext,
|
|
74
|
+
participants: this.participantsIndex,
|
|
64
75
|
...this.pugHelpers
|
|
65
76
|
}
|
|
66
77
|
|
|
67
|
-
|
|
68
|
-
const message = { content: renderedContent }
|
|
69
|
-
if (timeout) message.timeout = timeout
|
|
70
|
-
|
|
71
|
-
switch (displayType) {
|
|
78
|
+
switch (appRenderContext.meta.viewer) {
|
|
72
79
|
case 'participants':
|
|
73
80
|
logger.debug(`[DisplayEventProcessor] Publishing PARTICIPANTS_DISPLAY`)
|
|
81
|
+
|
|
74
82
|
return RealtimeMessaging.publish(
|
|
75
83
|
this.participantsDisplayChannel,
|
|
76
84
|
'PARTICIPANTS_DISPLAY',
|
|
77
|
-
|
|
85
|
+
template(templateRenderContext)
|
|
78
86
|
)
|
|
79
87
|
|
|
80
88
|
case 'spectators':
|
|
81
89
|
logger.debug(`[DisplayEventProcessor] Publishing SPECTATORS_DISPLAY`)
|
|
90
|
+
|
|
82
91
|
return RealtimeMessaging.publish(
|
|
83
92
|
this.spectatorsDisplayChannel,
|
|
84
93
|
'SPECTATORS_DISPLAY',
|
|
85
|
-
|
|
94
|
+
template(templateRenderContext)
|
|
86
95
|
)
|
|
87
96
|
|
|
88
97
|
case 'participant':
|
|
89
98
|
logger.debug(`[DisplayEventProcessor] Processing RENDER_DISPLAY for each participant`)
|
|
90
|
-
return this._processPrivateParticipantDisplays(template,
|
|
99
|
+
return this._processPrivateParticipantDisplays(template, templateRenderContext, timeout)
|
|
91
100
|
|
|
92
101
|
default:
|
|
93
|
-
throw new Error(`Unknown
|
|
102
|
+
throw new Error(`Unknown meta.viewer: ${appRenderContext.meta.viewer}`)
|
|
94
103
|
}
|
|
95
104
|
}
|
|
96
105
|
|
|
97
|
-
_processPrivateParticipantDisplays(template,
|
|
98
|
-
Object.values(this.
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
}
|
|
106
|
+
_processPrivateParticipantDisplays(template, templateRenderContext, timeout) {
|
|
107
|
+
Object.values(this.participantsIndex.all).forEach(
|
|
108
|
+
participantStruct => {
|
|
109
|
+
const participantId = participantStruct.info.id
|
|
110
|
+
const participantMachine = this.participantMachines[participantId]
|
|
111
|
+
const privateRenderContext = {
|
|
112
|
+
...templateRenderContext,
|
|
113
|
+
participant: participantStruct
|
|
114
|
+
}
|
|
107
115
|
|
|
108
|
-
|
|
116
|
+
const privateHtml = template(privateRenderContext)
|
|
109
117
|
|
|
110
|
-
|
|
111
|
-
|
|
118
|
+
const renderMessage = { content: privateHtml }
|
|
119
|
+
if (timeout) renderMessage.timeout = timeout
|
|
112
120
|
|
|
113
|
-
|
|
114
|
-
|
|
121
|
+
participantMachine.send('RENDER_DISPLAY', renderMessage)
|
|
122
|
+
}
|
|
123
|
+
)
|
|
115
124
|
|
|
116
125
|
return Promise.resolve()
|
|
117
126
|
}
|
|
@@ -18,44 +18,47 @@ const MetaProcessing = (anearEvent) => {
|
|
|
18
18
|
|
|
19
19
|
const appStateName = _stringifiedState(value)
|
|
20
20
|
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
const appRenderContext = (displayType, timeout = null) => (
|
|
22
|
+
{
|
|
23
|
+
app: appContext,
|
|
24
|
+
meta: {
|
|
25
|
+
state: appStateName,
|
|
26
|
+
event,
|
|
27
|
+
timeout,
|
|
28
|
+
viewer: displayType
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
)
|
|
26
32
|
|
|
27
33
|
const displayEvents = []
|
|
28
34
|
|
|
29
35
|
if (meta.participants) {
|
|
30
36
|
const viewPath = _getViewPath(meta.participants)
|
|
31
|
-
const timeout = _buildTimeout(meta.participants.timeout,
|
|
32
|
-
|
|
33
|
-
displayType: 'participants',
|
|
37
|
+
const timeout = _buildTimeout(meta.participants.timeout, appContext)
|
|
38
|
+
const displayEvent = {
|
|
34
39
|
viewPath,
|
|
35
|
-
timeout
|
|
36
|
-
|
|
37
|
-
|
|
40
|
+
appRenderContext: appRenderContext('participants', timeout)
|
|
41
|
+
}
|
|
42
|
+
displayEvents.push(displayEvent)
|
|
38
43
|
}
|
|
39
44
|
|
|
40
45
|
if (meta.participant) {
|
|
41
46
|
const viewPath = _getViewPath(meta.participant)
|
|
42
|
-
const timeout = _buildTimeout(meta.participant.timeout,
|
|
43
|
-
|
|
44
|
-
displayType: 'participant',
|
|
47
|
+
const timeout = _buildTimeout(meta.participant.timeout, appContext)
|
|
48
|
+
const displayEvent = {
|
|
45
49
|
viewPath,
|
|
46
|
-
timeout
|
|
47
|
-
|
|
48
|
-
|
|
50
|
+
appRenderContext: appRenderContext('participant', timeout)
|
|
51
|
+
}
|
|
52
|
+
displayEvents.push(displayEvent)
|
|
49
53
|
}
|
|
50
54
|
|
|
51
55
|
if (meta.spectators) {
|
|
52
56
|
const viewPath = _getViewPath(meta.spectators)
|
|
53
|
-
|
|
54
|
-
displayType: 'spectators',
|
|
57
|
+
const displayEvent = {
|
|
55
58
|
viewPath,
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
+
appRenderContext: appRenderContext('spectators')
|
|
60
|
+
}
|
|
61
|
+
displayEvents.push(displayEvent)
|
|
59
62
|
}
|
|
60
63
|
|
|
61
64
|
if (displayEvents.length > 0) {
|
|
@@ -72,11 +75,11 @@ const _getViewPath = (config) => {
|
|
|
72
75
|
throw new Error(`Unknown meta format: ${JSON.stringify(config)}`)
|
|
73
76
|
}
|
|
74
77
|
|
|
75
|
-
const _buildTimeout = (timeoutConfig,
|
|
78
|
+
const _buildTimeout = (timeoutConfig, appContext) => {
|
|
76
79
|
if (!timeoutConfig) return null
|
|
77
80
|
|
|
78
81
|
if (typeof timeoutConfig === 'function') {
|
|
79
|
-
const [msecs, participantId] = timeoutConfig(
|
|
82
|
+
const [msecs, participantId] = timeoutConfig(appContext)
|
|
80
83
|
return { msecs, participantId }
|
|
81
84
|
}
|
|
82
85
|
|