@viibe/impulse-integration-js 2.2.5 → 2.3.0

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.
@@ -0,0 +1,3 @@
1
+ {
2
+ "actions": []
3
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@viibe/impulse-integration-js",
3
- "version": "2.2.5",
3
+ "version": "2.3.0",
4
4
  "description": "ViiBE integration in js native",
5
5
  "main": "index.js",
6
6
  "publishConfig": {
package/src/index.js CHANGED
@@ -1,10 +1,21 @@
1
1
  class Viibe {
2
2
 
3
+ /**
4
+ * @typedef Handler
5
+ * @type {object}
6
+ * @property {string} eventName The name of the event to handle
7
+ * @property {string} windowName The name of the window / iframe to listen to
8
+ * @property {Function} func The function to trigger when an event is received
9
+ */
10
+
3
11
  constructor(options) {
12
+ /**
13
+ * @type {Handler[]}
14
+ */
15
+ this.handlers = []
4
16
  this.host = options.host
5
17
  this.origin = /^localhost/.test(this.host) ? `http://${this.host}` : `https://${this.host}`
6
18
  this.source = options.source
7
- this.handlers = {}
8
19
 
9
20
  window.addEventListener('message', this.onMessage.bind(this))
10
21
  }
@@ -16,6 +27,7 @@ class Viibe {
16
27
  const src = this.createCallUrl(options)
17
28
 
18
29
  const iframe = document.createElement('iframe')
30
+ iframe.name = 'viibe-' + Math.floor(Math.random() * 10000)
19
31
  iframe.style = 'border: 0;width: calc(100% - 1rem);margin: 0.5rem;'
20
32
  iframe.src = src
21
33
  iframe.allow = 'geolocation;autoplay;microphone;camera;midi;encrypted-media;clipboard-write;'
@@ -58,15 +70,15 @@ class Viibe {
58
70
 
59
71
  if (components) {
60
72
  let componentsParams = (components instanceof Array)
61
- ? components.join(',')
62
- : String(components)
73
+ ? components.join(',')
74
+ : String(components)
63
75
 
64
76
  params.set('components', componentsParams)
65
77
  }
66
78
 
67
79
  params.set('clipboard', Boolean(clipboard))
68
80
  params.set('o2m', Boolean(o2m))
69
-
81
+
70
82
  src += `?${params}`;
71
83
 
72
84
  return src
@@ -76,39 +88,80 @@ class Viibe {
76
88
  return Boolean(event.isTrusted && event.origin.indexOf(this.origin) === 0)
77
89
  }
78
90
 
79
- dispatch(eventName, payload) {
80
- const eventHandlers = this.handlers[eventName];
81
- if(!eventHandlers) {
82
- return null
83
- }
84
- return eventHandlers.map(handler => handler(payload))
91
+ /**
92
+ * Dispatches an event ie calls handlers corresponding to that event.
93
+ * Handlers with not windowName will be triggered regardless of the origin windowName
94
+ * Otherwise, the event will be triggered only if the handler windowName and the event windowName correspond
95
+ *
96
+ * @param {string} eventName
97
+ * @param {any} payload
98
+ * @param {string} windowName
99
+ * @returns
100
+ */
101
+ dispatch(eventName, payload, windowName) {
102
+ return this.handlers
103
+ .filter(handler =>
104
+ handler.eventName === eventName
105
+ && (!handler.windowName || (handler.windowName === windowName))
106
+ )
107
+ .map(handler => handler.func(payload))
85
108
  }
86
109
 
110
+ /**
111
+ * Handles postMessages / events received on the current window
112
+ * @param {any} event
113
+ * @returns
114
+ */
87
115
  onMessage(event) {
88
- if(!this.isViibeEvent(event)) {
116
+ if (!this.isViibeEvent(event)) {
89
117
  return null
90
118
  }
91
119
 
92
- if(event.data && event.data.event && event.data.payload) {
93
- return this.dispatch(event.data.event, event.data.payload)
120
+ if (event.data && event.data.event && event.data.payload) {
121
+ return this.dispatch(event.data.event, event.data.payload, event.data.windowName)
94
122
  }
95
123
 
96
124
  // FIXME: legacy authentication messages
97
- if(event.data && event.data.token) {
125
+ if (event.data && event.data.token) {
98
126
  return this.dispatch('authentication:token', event.data.token)
99
127
  }
100
- if(event.data && event.data.error) {
128
+ if (event.data && event.data.error) {
101
129
  return this.dispatch('authentication:error', event.data.error)
102
130
  }
103
131
 
104
132
  return null
105
133
  }
106
134
 
107
- on(eventName, handler) {
108
- const eventHandlers = this.handlers[eventName] = this.handlers[eventName] || []
109
- eventHandlers.push(handler);
135
+ /**
136
+ * Registers an event handler.
137
+ * Can be either called with 2 arguments (eventName and handler) to catch events from all iframes
138
+ * or with 3 arguments (iframe, eventName, handler) to catch events from only that iframe
139
+ * @param {HTMLIFrameElement} [iframe]
140
+ * @param {string} eventName
141
+ * @param {Function} handler
142
+ */
143
+ on(iframe, eventName, func) {
144
+ if (typeof iframe === 'string'
145
+ && typeof eventName === 'function'
146
+ && typeof func === 'undefined') {
147
+ func = eventName;
148
+ eventName = iframe;
149
+ iframe = null;
150
+ }
151
+
152
+ const handler = {
153
+ eventName,
154
+ windowName: iframe ? iframe.name : null,
155
+ func,
156
+ }
157
+ this.handlers.push(handler);
110
158
  }
111
-
159
+
160
+ /**
161
+ * Initiates an oauth login in a popup using the passed provider
162
+ * @param {string} provider A strategy name from the Viibe API (see /strategies API)
163
+ * @returns
164
+ */
112
165
  authenticate(provider) {
113
166
  const src = `${this.origin}/api/auth/login/${provider}`
114
167
  const width = 480
@@ -134,52 +187,57 @@ class Viibe {
134
187
 
135
188
  return new Promise((resolve, reject) => {
136
189
  const win = window.open(src, 'Authorization', windowParams.join(', '))
137
-
138
- if(!win) {
190
+
191
+ if (!win) {
139
192
  reject('Failed to open window')
140
193
  }
141
-
194
+
195
+ // pings the login window to check if it was closed
142
196
  const closeCheck = setInterval(() => {
143
- if(win.closed) {
197
+ if (win.closed) {
144
198
  destroy();
145
199
  onClose();
146
200
  }
147
-
201
+
148
202
  }, 100)
149
203
 
204
+ // triggered if the window was closed
150
205
  const onClose = () => {
151
206
  reject('User closed window')
152
207
  }
153
208
 
209
+ // completes the process, either because the user closes or because the authentication completed
210
+ // cleans intervals and event listeners
154
211
  const destroy = () => {
155
212
  window.removeEventListener('message', onMessage)
156
213
  clearInterval(closeCheck)
157
214
  }
158
215
 
216
+ // triggered when a message is received on the current window
159
217
  const onMessage = event => {
160
- if(!this.isViibeEvent(event)) {
218
+ if (!this.isViibeEvent(event)) {
161
219
  return null
162
220
  }
163
- if(event.data.token) {
221
+ if (event.data.token) {
164
222
  destroy();
165
223
  resolve(event.data.token)
166
224
  }
167
- if(event.data.error) {
225
+ if (event.data.error) {
168
226
  destroy();
169
227
  reject(event.data.error)
170
228
  }
171
229
  }
172
-
230
+
173
231
  window.addEventListener('message', onMessage)
174
232
  })
175
-
233
+
176
234
  }
177
235
 
178
236
  }
179
237
 
180
- if(typeof window !== 'undefined') {
238
+ if (typeof window !== 'undefined') {
181
239
  window.Viibe = Viibe
182
240
  }
183
- if(typeof module !== 'undefined') {
241
+ if (typeof module !== 'undefined') {
184
242
  module.exports = Viibe
185
243
  }