anear-js-api 0.4.29 → 0.4.31
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.
|
@@ -30,6 +30,7 @@ const AnearParticipantMachine = require('../state_machines/AnearParticipantMachi
|
|
|
30
30
|
const AnearParticipant = require('../models/AnearParticipant')
|
|
31
31
|
const RealtimeMessaging = require('../utils/RealtimeMessaging')
|
|
32
32
|
const MetaProcessing = require('../utils/MetaProcessing')
|
|
33
|
+
const DisplayEventProcessor = require('../utils/DisplayEventProcessor')
|
|
33
34
|
const PugHelpers = require('../utils/PugHelpers')
|
|
34
35
|
const C = require('../utils/Constants')
|
|
35
36
|
|
|
@@ -180,7 +181,7 @@ const ActiveEventStatesConfig = {
|
|
|
180
181
|
],
|
|
181
182
|
on: {
|
|
182
183
|
RENDER_DISPLAY: {
|
|
183
|
-
target: '
|
|
184
|
+
target: '.rendering'
|
|
184
185
|
}
|
|
185
186
|
},
|
|
186
187
|
states: {
|
|
@@ -196,7 +197,6 @@ const ActiveEventStatesConfig = {
|
|
|
196
197
|
}
|
|
197
198
|
},
|
|
198
199
|
rendering: {
|
|
199
|
-
id: 'rendering',
|
|
200
200
|
deferred: DeferredStatesPlus('ANNOUNCE', 'START'),
|
|
201
201
|
invoke: {
|
|
202
202
|
src: 'renderDisplay',
|
|
@@ -220,7 +220,7 @@ const ActiveEventStatesConfig = {
|
|
|
220
220
|
initial: 'transitioning',
|
|
221
221
|
on: {
|
|
222
222
|
RENDER_DISPLAY: {
|
|
223
|
-
target: '
|
|
223
|
+
target: '.rendering'
|
|
224
224
|
},
|
|
225
225
|
PARTICIPANT_LEAVE: {
|
|
226
226
|
// creator browser refresh or MIA. Send disconnect events
|
|
@@ -273,7 +273,6 @@ const ActiveEventStatesConfig = {
|
|
|
273
273
|
}
|
|
274
274
|
},
|
|
275
275
|
rendering: {
|
|
276
|
-
id: 'rendering',
|
|
277
276
|
deferred: DeferredStatesPlus('START'),
|
|
278
277
|
invoke: {
|
|
279
278
|
src: 'renderDisplay',
|
|
@@ -792,87 +791,10 @@ const AnearEventMachineFunctions = ({
|
|
|
792
791
|
}
|
|
793
792
|
},
|
|
794
793
|
services: {
|
|
795
|
-
renderDisplay:
|
|
796
|
-
const
|
|
797
|
-
const { displayType, viewPath, timeout, appExecutionContext } = displayEvent
|
|
798
|
-
|
|
799
|
-
logger.debug("processDisplayEvent - displayType: ", displayType, ", viewPath: ", viewPath)
|
|
800
|
-
|
|
801
|
-
const renderedDisplayContent = (template, additionalExecutionContext, timeout) => {
|
|
802
|
-
const renderedMessage = template(
|
|
803
|
-
{
|
|
804
|
-
displayType,
|
|
805
|
-
...appExecutionContext,
|
|
806
|
-
...additionalExecutionContext,
|
|
807
|
-
participants: context.participants,
|
|
808
|
-
...context.pugHelpers
|
|
809
|
-
}
|
|
810
|
-
)
|
|
811
|
-
const displayContent = { content: renderedMessage }
|
|
812
|
-
if (timeout) {
|
|
813
|
-
displayContent['timeout'] = timeout
|
|
814
|
-
}
|
|
815
|
-
return displayContent
|
|
816
|
-
}
|
|
817
|
-
|
|
818
|
-
const privateParticipantSend = participantMachine => {
|
|
819
|
-
const participantState = participantMachine.state
|
|
820
|
-
const participantContext = participantState.context
|
|
821
|
-
const { appParticipantMachine, anearParticipant } = participantContext
|
|
822
|
-
|
|
823
|
-
// TODO: don't send to participants that aren't in an active state
|
|
824
|
-
|
|
825
|
-
const appParticipantContext =
|
|
826
|
-
appParticipantMachine ? participantContext.appParticipantMachine.state.context : {}
|
|
827
|
-
|
|
828
|
-
const privateContext = {
|
|
829
|
-
anearParticipant: anearParticipant.participantInfo,
|
|
830
|
-
participantContext: appParticipantContext
|
|
831
|
-
}
|
|
794
|
+
renderDisplay: (context, event) => {
|
|
795
|
+
const displayEventProcessor = new DisplayEventProcessor(context)
|
|
832
796
|
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
participantMachine.send('PRIVATE_DISPLAY', displayEventPayload)
|
|
836
|
-
}
|
|
837
|
-
|
|
838
|
-
const normalizedPath = viewPath.endsWith(C.PugSuffix) ? viewPath : `${viewPath}${C.PugSuffix}`
|
|
839
|
-
const template = context.pugTemplates[normalizedPath]
|
|
840
|
-
if (!template) {
|
|
841
|
-
throw new Error(`Template not found for path "${normalizedPath}".`)
|
|
842
|
-
}
|
|
843
|
-
let displayMessage
|
|
844
|
-
|
|
845
|
-
switch (displayType) {
|
|
846
|
-
case 'participants':
|
|
847
|
-
displayMessage = renderedDisplayContent(template, {}, timeout)
|
|
848
|
-
return RealtimeMessaging.publish(
|
|
849
|
-
context.participantsDisplayChannel,
|
|
850
|
-
'PARTICIPANTS_DISPLAY',
|
|
851
|
-
displayMessage
|
|
852
|
-
)
|
|
853
|
-
break
|
|
854
|
-
case 'spectators':
|
|
855
|
-
displayMessage = renderedDisplayContent(template, {})
|
|
856
|
-
return RealtimeMessaging.publish(
|
|
857
|
-
context.spectatorsDisplayChannel,
|
|
858
|
-
'SPECTATORS_DISPLAY',
|
|
859
|
-
displayMessage
|
|
860
|
-
)
|
|
861
|
-
break
|
|
862
|
-
case 'participant':
|
|
863
|
-
// For private displays, iterate over active active participant machines.
|
|
864
|
-
Object.values(context.participantMachines).forEach(privateParticipantSend)
|
|
865
|
-
return Promise.resolve()
|
|
866
|
-
break
|
|
867
|
-
default:
|
|
868
|
-
throw new Error(`Unknown display type: ${displayType}`)
|
|
869
|
-
}
|
|
870
|
-
}
|
|
871
|
-
|
|
872
|
-
const publishPromises = event.displayEvents.map(
|
|
873
|
-
displayEvent => processDisplayEvent(context, displayEvent)
|
|
874
|
-
)
|
|
875
|
-
return Promise.all(publishPromises)
|
|
797
|
+
return displayEventProcessor.processAndPublish(event.displayEvents)
|
|
876
798
|
},
|
|
877
799
|
getAttachedCreatorOrHost: async (context, event) => {
|
|
878
800
|
logger.debug("getAttachedCreatorOrHost() invoked")
|
|
@@ -22,7 +22,7 @@ const CurrentDateTimestamp = _ => new Date().getTime()
|
|
|
22
22
|
const MISSING_TIMEOUT = 10000 // msecs
|
|
23
23
|
|
|
24
24
|
const DeferredStates = [
|
|
25
|
-
'
|
|
25
|
+
'RENDER_DISPLAY',
|
|
26
26
|
'PARTICIPANT_EXIT',
|
|
27
27
|
'PARTICIPANT_DISCONNECT',
|
|
28
28
|
'PARTICIPANT_RECONNECT'
|
|
@@ -92,8 +92,8 @@ const AnearParticipantMachineConfig = participantId => ({
|
|
|
92
92
|
idle: {
|
|
93
93
|
id: 'idle',
|
|
94
94
|
on: {
|
|
95
|
-
|
|
96
|
-
target: '#
|
|
95
|
+
RENDER_DISPLAY: {
|
|
96
|
+
target: '#renderDisplay'
|
|
97
97
|
},
|
|
98
98
|
PARTICIPANT_DISCONNECT: {
|
|
99
99
|
target: 'missing'
|
|
@@ -116,11 +116,11 @@ const AnearParticipantMachineConfig = participantId => ({
|
|
|
116
116
|
}
|
|
117
117
|
}
|
|
118
118
|
},
|
|
119
|
-
|
|
120
|
-
id: '
|
|
119
|
+
renderDisplay: {
|
|
120
|
+
id: 'renderDisplay',
|
|
121
121
|
deferred: DeferredStates,
|
|
122
122
|
invoke: {
|
|
123
|
-
src: '
|
|
123
|
+
src: 'participantDisplay',
|
|
124
124
|
onDone: [
|
|
125
125
|
{
|
|
126
126
|
cond: 'hasMetaTimeout',
|
|
@@ -233,7 +233,7 @@ const AnearParticipantMachineFunctions = {
|
|
|
233
233
|
}
|
|
234
234
|
},
|
|
235
235
|
services: {
|
|
236
|
-
|
|
236
|
+
participantDisplay: async (context, event) => {
|
|
237
237
|
await RealtimeMessaging.publish(
|
|
238
238
|
context.privateChannel,
|
|
239
239
|
'PRIVATE_DISPLAY',
|
|
@@ -248,7 +248,7 @@ const AnearParticipantMachineFunctions = {
|
|
|
248
248
|
},
|
|
249
249
|
guards: {
|
|
250
250
|
hasAppParticipantMachine: context => context.appParticipantMachineFactory !== null,
|
|
251
|
-
hasMetaTimeout: (context, event) => event.data.timeout
|
|
251
|
+
hasMetaTimeout: (context, event) => event.data.timeout?.msecs > 0
|
|
252
252
|
},
|
|
253
253
|
delays: {
|
|
254
254
|
timeoutMsecsAfterNoResponse: context => context.noResponseTimeout
|
|
@@ -258,7 +258,7 @@ const AnearParticipantMachineFunctions = {
|
|
|
258
258
|
// The AnearParticipantMachine:
|
|
259
259
|
// 1. maintains the presence and geo-location for a Participant in an Event
|
|
260
260
|
// 2. instantiates the XState Machine return by the (optional) appParticipantMachineFactory
|
|
261
|
-
// 3. creates a private display ChannelMachine to which any
|
|
261
|
+
// 3. creates a private display ChannelMachine to which any participant displayType messages get published
|
|
262
262
|
// 4. handles activity state, response timeouts, idle state
|
|
263
263
|
// 5. receives ACTION events relayed by the AnearEventMachine
|
|
264
264
|
// 6. relays all relevant events to the participant XState Machine for Application-specific handling
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"use strict"
|
|
2
|
+
/**
|
|
3
|
+
* --------------------------------------------------------------------------
|
|
4
|
+
* Pug templates receive the following context at render:
|
|
5
|
+
*
|
|
6
|
+
* {
|
|
7
|
+
* displayType: // 'participants' | 'spectators' | 'participant'
|
|
8
|
+
* context: // AppEventMachine's XState context for this transition
|
|
9
|
+
* state: // Stringified state name (e.g., 'live.registration.waitForOpponentToJoin')
|
|
10
|
+
* event: // The triggering event for this transition
|
|
11
|
+
* participants: // Map of all participants for this event
|
|
12
|
+
*
|
|
13
|
+
* // When 'participant' displayType
|
|
14
|
+
* participant // current participant
|
|
15
|
+
* participantContext // current participant private context if AppParticipantMachine
|
|
16
|
+
*
|
|
17
|
+
* // PLUS all helpers from PugHelpers:
|
|
18
|
+
* cdnImg(filename) // Resolves CDN image path
|
|
19
|
+
* action(payload) // JSON-encodes click action payloads for data attributes
|
|
20
|
+
* }
|
|
21
|
+
*
|
|
22
|
+
* Example usage in Pug:
|
|
23
|
+
*
|
|
24
|
+
* img(src=cdnImg('logo.png'))
|
|
25
|
+
* .sq(data-anear-click=action({MOVE: {x, y}}))
|
|
26
|
+
* each participant in Object.values(participants)
|
|
27
|
+
* li= participant.name
|
|
28
|
+
*
|
|
29
|
+
* --------------------------------------------------------------------------
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
const logger = require('./Logger')
|
|
33
|
+
const RealtimeMessaging = require('./RealtimeMessaging')
|
|
34
|
+
const C = require('./Constants')
|
|
35
|
+
|
|
36
|
+
class DisplayEventProcessor {
|
|
37
|
+
constructor(anearEventMachineContext) {
|
|
38
|
+
this.pugTemplates = anearEventMachineContext.pugTemplates
|
|
39
|
+
this.pugHelpers = anearEventMachineContext.pugHelpers
|
|
40
|
+
this.participants = anearEventMachineContext.participants
|
|
41
|
+
this.participantMachines = anearEventMachineContext.participantMachines
|
|
42
|
+
this.participantsDisplayChannel = anearEventMachineContext.participantsDisplayChannel
|
|
43
|
+
this.spectatorsDisplayChannel = anearEventMachineContext.spectatorsDisplayChannel
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
processAndPublish(displayEvents) {
|
|
47
|
+
return Promise.all(displayEvents.map(event => this._processSingle(event)))
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
_processSingle(displayEvent) {
|
|
51
|
+
const { displayType, viewPath, timeout, appExecutionContext } = displayEvent
|
|
52
|
+
|
|
53
|
+
const normalizedPath = viewPath.endsWith(C.PugSuffix) ? viewPath : `${viewPath}${C.PugSuffix}`
|
|
54
|
+
const template = this.pugTemplates[normalizedPath]
|
|
55
|
+
|
|
56
|
+
if (!template) {
|
|
57
|
+
throw new Error(`Template not found: ${normalizedPath}`)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const renderContext = {
|
|
61
|
+
displayType,
|
|
62
|
+
...appExecutionContext,
|
|
63
|
+
participants: this.participants,
|
|
64
|
+
...this.pugHelpers
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const renderedContent = template(renderContext)
|
|
68
|
+
const message = { content: renderedContent }
|
|
69
|
+
if (timeout) message.timeout = timeout
|
|
70
|
+
|
|
71
|
+
switch (displayType) {
|
|
72
|
+
case 'participants':
|
|
73
|
+
logger.debug(`[DisplayEventProcessor] Publishing PARTICIPANTS_DISPLAY`)
|
|
74
|
+
return RealtimeMessaging.publish(
|
|
75
|
+
this.participantsDisplayChannel,
|
|
76
|
+
'PARTICIPANTS_DISPLAY',
|
|
77
|
+
message.content
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
case 'spectators':
|
|
81
|
+
logger.debug(`[DisplayEventProcessor] Publishing SPECTATORS_DISPLAY`)
|
|
82
|
+
return RealtimeMessaging.publish(
|
|
83
|
+
this.spectatorsDisplayChannel,
|
|
84
|
+
'SPECTATORS_DISPLAY',
|
|
85
|
+
message.content
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
case 'participant':
|
|
89
|
+
logger.debug(`[DisplayEventProcessor] Processing RENDER_DISPLAY for each participant`)
|
|
90
|
+
return this._processPrivateParticipantDisplays(template, renderContext, timeout)
|
|
91
|
+
|
|
92
|
+
default:
|
|
93
|
+
throw new Error(`Unknown displayType: ${displayType}`)
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
_processPrivateParticipantDisplays(template, renderContextBase, timeout) {
|
|
98
|
+
Object.values(this.participantMachines).forEach(participantMachine => {
|
|
99
|
+
const participantState = participantMachine.state
|
|
100
|
+
const { anearParticipant, appParticipantMachine } = participantState.context
|
|
101
|
+
|
|
102
|
+
const privateRenderContext = {
|
|
103
|
+
...renderContextBase,
|
|
104
|
+
participant: anearParticipant.participantInfo,
|
|
105
|
+
participantContext: appParticipantMachine?.state?.context || {}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const privateHtml = template(privateRenderContext)
|
|
109
|
+
|
|
110
|
+
const renderMessage = { content: privateHtml }
|
|
111
|
+
if (timeout) renderMessage.timeout = timeout
|
|
112
|
+
|
|
113
|
+
participantMachine.send('RENDER_DISPLAY', renderMessage)
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
return Promise.resolve()
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
module.exports = DisplayEventProcessor
|
|
@@ -2,146 +2,94 @@
|
|
|
2
2
|
|
|
3
3
|
const logger = require('./Logger')
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
switch (timeoutType) {
|
|
22
|
-
case 'participant':
|
|
23
|
-
return { type: timeoutType, msecs, participantId }
|
|
24
|
-
case 'participants':
|
|
25
|
-
return { type: timeoutType, msecs }
|
|
26
|
-
default:
|
|
27
|
-
throw new Error(`unknown timeout type ${timeoutType}`)
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
const metaConfig = (meta, timeoutType, appExecutionContext) => {
|
|
32
|
-
let timeout = {msecs: 0}
|
|
33
|
-
let view = null
|
|
34
|
-
|
|
35
|
-
switch (typeof meta) {
|
|
36
|
-
case 'string':
|
|
37
|
-
view = meta
|
|
38
|
-
break
|
|
39
|
-
case 'object':
|
|
40
|
-
view = meta.view
|
|
41
|
-
if (meta.timeout) {
|
|
42
|
-
timeout = buildTimeout(timeoutType, meta.timeout, appExecutionContext)
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
break
|
|
46
|
-
default:
|
|
47
|
-
throw new Error(`unknown ${timeoutType} meta format ${meta}`)
|
|
48
|
-
}
|
|
49
|
-
return [view, timeout]
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const participantsMetaConfig = (participantsMeta, appExecutionContext) => {
|
|
53
|
-
return metaConfig(participantsMeta, 'participants', appExecutionContext)
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
const participantMetaConfig = (participantMeta, appExecutionContext) => {
|
|
57
|
-
return metaConfig(participantMeta, 'participant', appExecutionContext)
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
const spectatorMetaConfig = config => {
|
|
61
|
-
if (typeof config === 'string')
|
|
62
|
-
return config
|
|
63
|
-
else if (typeof config === 'object')
|
|
64
|
-
return config.view
|
|
65
|
-
else
|
|
66
|
-
throw new Error(`unknown spectator meta format ${config}`)
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
const Stringified = (stateValue) => {
|
|
70
|
-
switch (typeof stateValue) {
|
|
71
|
-
case 'string':
|
|
72
|
-
return stateValue
|
|
73
|
-
case 'object':
|
|
74
|
-
return Object.entries(stateValue)
|
|
75
|
-
.map(([key, nested]) => `${key}.${Stringified(nested)}`)
|
|
76
|
-
.join('.')
|
|
77
|
-
default:
|
|
78
|
-
throw new Error(`unknown Xstate state value type ${typeof stateValue}`)
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
const MetaProcessing = anearEvent => {
|
|
83
|
-
return appEventMachineState => {
|
|
84
|
-
const { context: appContext, meta: rawMeta } = appEventMachineState
|
|
85
|
-
const appStateName = Stringified(appEventMachineState.value)
|
|
86
|
-
const displayEvents = []
|
|
87
|
-
|
|
88
|
-
//logger.debug("MetaProcessing invoked on transition to: ", appStateName)
|
|
89
|
-
//logger.debug("stateMeta: ", appEventMachineState.meta)
|
|
90
|
-
|
|
91
|
-
if (Object.keys(appEventMachineState.meta).length === 0) {
|
|
92
|
-
return
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
logger.debug("App Context: ", appContext)
|
|
96
|
-
|
|
97
|
-
const sendDisplayMessage = () => {
|
|
98
|
-
logger.debug(`${appStateName} 'RENDER_DISPLAY' to ${anearEvent.id} with ${displayEvents.length} msgs`)
|
|
99
|
-
|
|
100
|
-
// sends a RENDER_DISPLAY event with one or more viewPaths and appExecutionContext in the displayEvents array
|
|
101
|
-
anearEvent.send('RENDER_DISPLAY', { displayEvents })
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
const appendDisplayEvent = (displayType, viewPath, timeout = null) => {
|
|
105
|
-
displayEvents.push(
|
|
106
|
-
{
|
|
107
|
-
displayType,
|
|
108
|
-
viewPath,
|
|
109
|
-
timeout,
|
|
110
|
-
appExecutionContext
|
|
111
|
-
}
|
|
112
|
-
)
|
|
113
|
-
}
|
|
5
|
+
/**
|
|
6
|
+
* MetaProcessing:
|
|
7
|
+
* - Runs inside your appEventMachine onTransition.
|
|
8
|
+
* - Knows how to parse the XState meta shape (participants, participant, spectators).
|
|
9
|
+
* - Normalizes viewPath + timeout.
|
|
10
|
+
* - Emits displayEvents → sends to AnearEventMachine for rendering.
|
|
11
|
+
*/
|
|
12
|
+
const MetaProcessing = (anearEvent) => {
|
|
13
|
+
return (appEventMachineState) => {
|
|
14
|
+
const { meta: rawMeta, context: appContext, value, event } = appEventMachineState
|
|
15
|
+
const [meta] = Object.values(rawMeta)
|
|
16
|
+
|
|
17
|
+
if (!meta) return
|
|
18
|
+
|
|
19
|
+
const appStateName = _stringifiedState(value)
|
|
114
20
|
|
|
115
21
|
const appExecutionContext = {
|
|
116
22
|
context: appContext,
|
|
117
23
|
state: appStateName,
|
|
118
|
-
event
|
|
24
|
+
event
|
|
119
25
|
}
|
|
120
26
|
|
|
121
|
-
const
|
|
122
|
-
|
|
123
|
-
logger.debug("meta: ", meta)
|
|
124
|
-
|
|
125
|
-
// Only proceed if there's at least one display meta defined.
|
|
126
|
-
if (!meta.participants && !meta.participant && !meta.spectators) return
|
|
27
|
+
const displayEvents = []
|
|
127
28
|
|
|
128
29
|
if (meta.participants) {
|
|
129
|
-
const
|
|
130
|
-
|
|
30
|
+
const viewPath = _getViewPath(meta.participants)
|
|
31
|
+
const timeout = _buildTimeout(meta.participants.timeout, appExecutionContext)
|
|
32
|
+
displayEvents.push({
|
|
33
|
+
displayType: 'participants',
|
|
34
|
+
viewPath,
|
|
35
|
+
timeout,
|
|
36
|
+
appExecutionContext
|
|
37
|
+
})
|
|
131
38
|
}
|
|
132
39
|
|
|
133
40
|
if (meta.participant) {
|
|
134
|
-
const
|
|
135
|
-
|
|
41
|
+
const viewPath = _getViewPath(meta.participant)
|
|
42
|
+
const timeout = _buildTimeout(meta.participant.timeout, appExecutionContext)
|
|
43
|
+
displayEvents.push({
|
|
44
|
+
displayType: 'participant',
|
|
45
|
+
viewPath,
|
|
46
|
+
timeout,
|
|
47
|
+
appExecutionContext
|
|
48
|
+
})
|
|
136
49
|
}
|
|
137
50
|
|
|
138
51
|
if (meta.spectators) {
|
|
139
|
-
const viewPath =
|
|
140
|
-
|
|
52
|
+
const viewPath = _getViewPath(meta.spectators)
|
|
53
|
+
displayEvents.push({
|
|
54
|
+
displayType: 'spectators',
|
|
55
|
+
viewPath,
|
|
56
|
+
timeout: null,
|
|
57
|
+
appExecutionContext
|
|
58
|
+
})
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (displayEvents.length > 0) {
|
|
62
|
+
logger.debug(`[MetaProcessing] sending RENDER_DISPLAY with ${displayEvents.length} displayEvents`)
|
|
63
|
+
anearEvent.send('RENDER_DISPLAY', { displayEvents })
|
|
141
64
|
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const _getViewPath = (config) => {
|
|
69
|
+
if (!config) return null
|
|
70
|
+
if (typeof config === 'string') return config
|
|
71
|
+
if (typeof config === 'object') return config.view
|
|
72
|
+
throw new Error(`Unknown meta format: ${JSON.stringify(config)}`)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const _buildTimeout = (timeoutConfig, appExecutionContext) => {
|
|
76
|
+
if (!timeoutConfig) return null
|
|
142
77
|
|
|
143
|
-
|
|
78
|
+
if (typeof timeoutConfig === 'function') {
|
|
79
|
+
const [msecs, participantId] = timeoutConfig(appExecutionContext)
|
|
80
|
+
return { msecs, participantId }
|
|
144
81
|
}
|
|
82
|
+
|
|
83
|
+
if (typeof timeoutConfig === 'number') {
|
|
84
|
+
return { msecs: timeoutConfig }
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
throw new Error(`Unknown timeout config: ${typeof timeoutConfig}`)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const _stringifiedState = (stateValue) => {
|
|
91
|
+
if (typeof stateValue === 'string') return stateValue
|
|
92
|
+
return Object.entries(stateValue).map(([k, v]) => `${k}.${_stringifiedState(v)}`).join('.')
|
|
145
93
|
}
|
|
146
94
|
|
|
147
95
|
module.exports = MetaProcessing
|