@seamly/web-ui 21.0.2 → 21.0.3-beta.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seamly/web-ui",
3
- "version": "21.0.2",
3
+ "version": "21.0.3-beta.2",
4
4
  "main": "build/dist/lib/index.js",
5
5
  "types": "build/src/javascripts/index.d.ts",
6
6
  "module": "",
@@ -4,16 +4,21 @@ import debug from 'lib/debug'
4
4
  import splitUrlParams from 'lib/split-url-params'
5
5
 
6
6
  const log = debug('seamly')
7
-
8
- type ConnectionState =
7
+ type CurrentConnectionState =
9
8
  | 'socket_closed' // Socket is closed.
10
9
  | 'channel_closed' // Channel is closed.
11
10
  | 'channel_erred' // Errors received from joined channel.
12
11
  | 'join_channel_succeeded' // Joined channel succesfully.
13
12
  | 'join_channel_erred' // Error on joining channel. This is usefull when you want to restart a chat sessions.
14
13
  | 'attach_channel_succeeded' // Attached channel to system.
14
+
15
+ type ConnectionState = {
16
+ connected: boolean
17
+ ready: boolean
18
+ currentState: CurrentConnectionState
19
+ }
15
20
  export default class ConversationConnector {
16
- #connectionListeners = []
21
+ #connectionListeners: ((_payload: ConnectionState) => boolean | void)[] = []
17
22
 
18
23
  accessToken: string
19
24
 
@@ -64,24 +69,40 @@ export default class ConversationConnector {
64
69
  this.channel.on('system', (msg) => {
65
70
  switch (msg.type) {
66
71
  case 'attach_channel_succeeded':
67
- this.#emitConnectionState('attach_channel_succeeded')
72
+ this.#emitConnectionState({
73
+ connected: true,
74
+ ready: true,
75
+ currentState: 'attach_channel_succeeded',
76
+ })
68
77
  break
69
78
  }
70
79
  })
71
80
 
72
81
  this.socket.onClose(() => {
73
82
  log('[SOCKET]CLOSE')
74
- this.#emitConnectionState('socket_closed')
83
+ this.#emitConnectionState({
84
+ connected: false,
85
+ ready: false,
86
+ currentState: 'socket_closed',
87
+ })
75
88
  })
76
89
 
77
90
  this.channel.onClose(() => {
78
91
  log('[CHANNEL]CLOSE')
79
- this.#emitConnectionState('channel_closed')
92
+ this.#emitConnectionState({
93
+ connected: false,
94
+ ready: false,
95
+ currentState: 'channel_closed',
96
+ })
80
97
  })
81
98
 
82
99
  this.channel.onError((msg) => {
83
100
  log('[CHANNEL][ERROR]', msg)
84
- this.#emitConnectionState('channel_erred')
101
+ this.#emitConnectionState({
102
+ connected: false,
103
+ ready: false,
104
+ currentState: 'channel_erred',
105
+ })
85
106
  })
86
107
 
87
108
  this.#listenTo(
@@ -102,11 +123,19 @@ export default class ConversationConnector {
102
123
  .join()
103
124
  .receive('ok', () => {
104
125
  log('[CHANNEL][JOIN] OK')
105
- this.#emitConnectionState('join_channel_succeeded')
126
+ this.#emitConnectionState({
127
+ connected: true,
128
+ ready: false,
129
+ currentState: 'join_channel_succeeded',
130
+ })
106
131
  })
107
132
  .receive('error', (err) => {
108
133
  log('[CHANNEL][JOIN] ERROR', err)
109
- this.#emitConnectionState('join_channel_erred')
134
+ this.#emitConnectionState({
135
+ connected: false,
136
+ ready: false,
137
+ currentState: 'join_channel_erred',
138
+ })
110
139
  // @ts-ignore
111
140
  this.channel.socket.disconnect()
112
141
  })
@@ -130,13 +159,21 @@ export default class ConversationConnector {
130
159
  })
131
160
  }
132
161
 
133
- // eslint-disable-next-line no-unused-vars
134
- onConnection(cb: (_payload: ConnectionState) => void) {
162
+ onConnection(cb: (_payload: ConnectionState) => boolean | void) {
135
163
  this.#connectionListeners.push(cb)
136
164
  }
137
165
 
138
166
  #emitConnectionState(payload: ConnectionState) {
139
- this.#connectionListeners.forEach((cb) => cb(payload))
167
+ // Loop in reverse order to enable splicing the array while iterating
168
+ for (let i = this.#connectionListeners.length - 1; i >= 0; i--) {
169
+ const callback = this.#connectionListeners[i]
170
+ const complete = callback(payload)
171
+
172
+ // If we only want to execute the callback once, remove it from the listener
173
+ if (complete) {
174
+ this.#connectionListeners.splice(i, 1)
175
+ }
176
+ }
140
177
  }
141
178
 
142
179
  pushToChannel(
@@ -382,12 +382,9 @@ export class API {
382
382
  this.#getAccessToken(),
383
383
  )
384
384
 
385
- this.conversation.onConnection((connectionState) => {
386
- this.connected = [
387
- 'attach_channel_succeeded',
388
- 'join_channel_succeeded',
389
- ].includes(connectionState)
390
- this.#ready = connectionState === 'attach_channel_succeeded'
385
+ this.conversation.onConnection(({ connected, ready }) => {
386
+ this.connected = connected
387
+ this.#ready = ready
391
388
  })
392
389
 
393
390
  // Send environment
@@ -490,13 +487,18 @@ export class API {
490
487
  send(command, payload, waitForReady = true) {
491
488
  if (!this.connected || (waitForReady && !this.#ready)) {
492
489
  // Wait for connection to be made
493
- this.conversation?.onConnection((connectionState) => {
494
- const connected = connectionState === 'join_channel_succeeded'
495
- const ready = connectionState === 'attach_channel_succeeded'
496
- if (connected || ready) {
490
+ this.conversation?.onConnection(({ connected, ready }) => {
491
+ this.connected = connected
492
+ this.#ready = ready
493
+
494
+ if (waitForReady ? ready : connected) {
497
495
  this.send(command, payload, waitForReady)
496
+ return true
498
497
  }
498
+
499
+ return false
499
500
  })
501
+
500
502
  return
501
503
  }
502
504
 
@@ -76,8 +76,8 @@ const SeamlyEventSubscriber = () => {
76
76
  }, [api, api.connectionInfo, api.conversation])
77
77
 
78
78
  useEffect(() => {
79
- api.conversation.onConnection((connectionState) => {
80
- if (connectionState === 'join_channel_erred') {
79
+ api.conversation.onConnection(({ currentState }) => {
80
+ if (currentState === 'join_channel_erred') {
81
81
  const seamlyGeneralError = new SeamlyGeneralError()
82
82
  dispatch(
83
83
  setInterrupt({
@@ -1,6 +1,5 @@
1
1
  import ChatFrame from 'ui/components/layout/deprecated-chat-frame'
2
2
  import { useShowInlineView, useVisibility } from 'domains/visibility/hooks'
3
- import { useSeamlyChat } from '../../hooks/seamly-hooks'
4
3
  import Conversation from '../conversation/conversation'
5
4
  import DeprecatedToggleButton from '../entry/deprecated-toggle-button'
6
5
  import AgentInfo from '../layout/agent-info'
@@ -15,7 +14,6 @@ const ShowInlineView = ({ children }) => {
15
14
  }
16
15
 
17
16
  const DeprecatedView = () => {
18
- useSeamlyChat()
19
17
  const { isVisible, openChat, closeChat } = useVisibility()
20
18
 
21
19
  return (