@hellotext/hellotext 2.5.7 → 2.5.8
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/README.md +0 -25
- package/dist/hellotext.js +1 -1
- package/index.d.ts +0 -6
- package/lib/api/acks.cjs +17 -31
- package/lib/api/acks.js +17 -42
- package/lib/api/businesses.cjs +14 -28
- package/lib/api/businesses.js +13 -36
- package/lib/api/events.cjs +26 -40
- package/lib/api/events.js +28 -52
- package/lib/api/forms.cjs +24 -40
- package/lib/api/forms.js +24 -57
- package/lib/api/identifications.cjs +15 -29
- package/lib/api/identifications.js +15 -40
- package/lib/api/index.cjs +25 -51
- package/lib/api/index.js +27 -54
- package/lib/api/push/identities.cjs +30 -46
- package/lib/api/push/identities.js +30 -63
- package/lib/api/response.cjs +30 -52
- package/lib/api/response.js +31 -60
- package/lib/api/submissions.cjs +18 -34
- package/lib/api/submissions.js +18 -48
- package/lib/api/webchat/messages.cjs +44 -64
- package/lib/api/webchat/messages.js +44 -80
- package/lib/api/webchats.cjs +37 -56
- package/lib/api/webchats.js +37 -65
- package/lib/api/whatsapp_widgets.cjs +49 -72
- package/lib/api/whatsapp_widgets.js +48 -91
- package/lib/builders/input_builder.cjs +36 -48
- package/lib/builders/input_builder.js +36 -48
- package/lib/builders/logo_builder.cjs +10 -29
- package/lib/builders/logo_builder.js +20 -28
- package/lib/channels/application_channel.cjs +136 -178
- package/lib/channels/application_channel.js +137 -180
- package/lib/channels/webchat_channel.cjs +125 -170
- package/lib/channels/webchat_channel.js +125 -170
- package/lib/controllers/form_controller.cjs +82 -121
- package/lib/controllers/form_controller.js +82 -130
- package/lib/controllers/message_controller.cjs +211 -282
- package/lib/controllers/message_controller.js +209 -284
- package/lib/controllers/mixins/usePopover.cjs +3 -6
- package/lib/controllers/mixins/usePopover.js +17 -22
- package/lib/controllers/webchat/emoji_picker_controller.cjs +106 -150
- package/lib/controllers/webchat/emoji_picker_controller.js +105 -170
- package/lib/controllers/webchat/useBehaviour.js +5 -5
- package/lib/controllers/webchat/useOpeningSequence.js +6 -6
- package/lib/controllers/webchat/useTeaser.js +9 -9
- package/lib/controllers/webchat_controller.cjs +916 -1088
- package/lib/controllers/webchat_controller.js +926 -1152
- package/lib/core/configuration/forms.cjs +21 -35
- package/lib/core/configuration/forms.js +20 -35
- package/lib/core/configuration/locale.cjs +36 -71
- package/lib/core/configuration/locale.js +36 -70
- package/lib/core/configuration/push.cjs +9 -21
- package/lib/core/configuration/push.js +8 -20
- package/lib/core/configuration/webchat.cjs +142 -182
- package/lib/core/configuration/webchat.js +145 -189
- package/lib/core/configuration/whatsapp.cjs +76 -102
- package/lib/core/configuration/whatsapp.js +76 -105
- package/lib/core/configuration.cjs +60 -78
- package/lib/core/configuration.js +59 -78
- package/lib/core/event.cjs +36 -59
- package/lib/core/event.js +35 -61
- package/lib/core/sanitize_html.js +4 -4
- package/lib/errors/invalid_event.cjs +5 -26
- package/lib/errors/invalid_event.js +5 -26
- package/lib/errors/not_initialized_error.cjs +5 -26
- package/lib/errors/not_initialized_error.js +5 -26
- package/lib/hellotext.cjs +185 -223
- package/lib/hellotext.js +188 -247
- package/lib/index.js +1 -1
- package/lib/models/business.cjs +114 -152
- package/lib/models/business.js +117 -162
- package/lib/models/cookies.cjs +34 -51
- package/lib/models/cookies.js +34 -51
- package/lib/models/fingerprint.cjs +8 -23
- package/lib/models/fingerprint.js +25 -58
- package/lib/models/form.cjs +106 -142
- package/lib/models/form.js +105 -153
- package/lib/models/form_collection.cjs +63 -101
- package/lib/models/form_collection.js +61 -107
- package/lib/models/page.cjs +106 -129
- package/lib/models/page.js +106 -131
- package/lib/models/push.cjs +278 -322
- package/lib/models/push.js +284 -357
- package/lib/models/query.cjs +21 -41
- package/lib/models/query.js +21 -41
- package/lib/models/session.cjs +33 -65
- package/lib/models/session.js +30 -63
- package/lib/models/user.cjs +29 -51
- package/lib/models/user.js +29 -51
- package/lib/models/utm.cjs +15 -27
- package/lib/models/utm.js +17 -32
- package/lib/models/webchat.cjs +52 -76
- package/lib/models/webchat.js +52 -90
- package/lib/models/whatsapp_widget.cjs +41 -59
- package/lib/models/whatsapp_widget.js +41 -73
- package/lib/vanilla.cjs +4 -7
- package/lib/vanilla.js +2 -1
- package/package.json +1 -9
- package/src/index.bundle.js +0 -1
- package/src/vanilla.js +2 -1
- package/styles/index.css +0 -30
|
@@ -5,199 +5,157 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.default = void 0;
|
|
7
7
|
var _core = require("../core");
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
8
|
+
class ApplicationChannel {
|
|
9
|
+
static webSocket;
|
|
10
|
+
static channels = new Set();
|
|
11
|
+
static messageHandlers = new Set();
|
|
12
|
+
static disconnectHandlers = new Set();
|
|
13
|
+
static subscriptionConfirmHandlers = new Set();
|
|
14
|
+
static reconnectTimeout = null;
|
|
15
|
+
static reconnectAttempts = 0;
|
|
16
|
+
static reconnectBaseDelay = 500;
|
|
17
|
+
static reconnectMaxDelay = 10000;
|
|
18
|
+
static reconnectJitter = 0.3;
|
|
19
|
+
static needsResubscribe = false;
|
|
20
|
+
constructor() {
|
|
16
21
|
ApplicationChannel.channels.add(this);
|
|
17
22
|
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
23
|
+
send({
|
|
24
|
+
command,
|
|
25
|
+
identifier,
|
|
26
|
+
data
|
|
27
|
+
}) {
|
|
28
|
+
const payload = {
|
|
21
29
|
command,
|
|
22
|
-
identifier,
|
|
23
|
-
data
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
const message = JSON.stringify(payload);
|
|
32
|
-
if (socket.readyState === WebSocket.OPEN) {
|
|
30
|
+
identifier: JSON.stringify(identifier),
|
|
31
|
+
data: JSON.stringify(data || {})
|
|
32
|
+
};
|
|
33
|
+
const socket = ApplicationChannel.ensureWebSocket();
|
|
34
|
+
const message = JSON.stringify(payload);
|
|
35
|
+
if (socket.readyState === WebSocket.OPEN) {
|
|
36
|
+
socket.send(message);
|
|
37
|
+
} else {
|
|
38
|
+
socket.addEventListener('open', () => {
|
|
33
39
|
socket.send(message);
|
|
34
|
-
} else {
|
|
35
|
-
socket.addEventListener('open', () => {
|
|
36
|
-
socket.send(message);
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
}, {
|
|
41
|
-
key: "onMessage",
|
|
42
|
-
value: function onMessage(callback) {
|
|
43
|
-
const handler = event => {
|
|
44
|
-
const data = JSON.parse(event.data);
|
|
45
|
-
const {
|
|
46
|
-
type,
|
|
47
|
-
message
|
|
48
|
-
} = data;
|
|
49
|
-
if (this.ignoredEvents.includes(type)) {
|
|
50
|
-
return;
|
|
51
|
-
}
|
|
52
|
-
callback(message);
|
|
53
|
-
};
|
|
54
|
-
ApplicationChannel.messageHandlers.add(handler);
|
|
55
|
-
ApplicationChannel.ensureWebSocket().addEventListener('message', handler);
|
|
56
|
-
}
|
|
57
|
-
}, {
|
|
58
|
-
key: "onDisconnect",
|
|
59
|
-
value: function onDisconnect(callback) {
|
|
60
|
-
ApplicationChannel.disconnectHandlers.add(callback);
|
|
61
|
-
}
|
|
62
|
-
}, {
|
|
63
|
-
key: "onSubscriptionConfirmed",
|
|
64
|
-
value: function onSubscriptionConfirmed(callback) {
|
|
65
|
-
ApplicationChannel.subscriptionConfirmHandlers.add(callback);
|
|
66
|
-
}
|
|
67
|
-
}, {
|
|
68
|
-
key: "webSocket",
|
|
69
|
-
get: function () {
|
|
70
|
-
return ApplicationChannel.ensureWebSocket();
|
|
71
|
-
}
|
|
72
|
-
}, {
|
|
73
|
-
key: "ignoredEvents",
|
|
74
|
-
get: function () {
|
|
75
|
-
return ['ping', 'confirm_subscription', 'welcome'];
|
|
76
|
-
}
|
|
77
|
-
}], [{
|
|
78
|
-
key: "ensureWebSocket",
|
|
79
|
-
value: function ensureWebSocket() {
|
|
80
|
-
if (this.webSocket && !this.closedWebSocket(this.webSocket)) {
|
|
81
|
-
return this.webSocket;
|
|
82
|
-
}
|
|
83
|
-
if (this.webSocket) {
|
|
84
|
-
this.needsResubscribe = true;
|
|
85
|
-
}
|
|
86
|
-
return this.openWebSocket();
|
|
87
|
-
}
|
|
88
|
-
}, {
|
|
89
|
-
key: "openWebSocket",
|
|
90
|
-
value: function openWebSocket() {
|
|
91
|
-
this.clearReconnectTimeout();
|
|
92
|
-
const socket = new WebSocket(_core.Configuration.actionCableUrl);
|
|
93
|
-
this.webSocket = socket;
|
|
94
|
-
this.installWebSocketHandlers(socket);
|
|
95
|
-
return socket;
|
|
96
|
-
}
|
|
97
|
-
}, {
|
|
98
|
-
key: "installWebSocketHandlers",
|
|
99
|
-
value: function installWebSocketHandlers(socket) {
|
|
100
|
-
socket.addEventListener('open', () => this.handleOpen(socket));
|
|
101
|
-
socket.addEventListener('close', () => this.handleDisconnect(socket));
|
|
102
|
-
socket.addEventListener('error', () => this.handleDisconnect(socket));
|
|
103
|
-
socket.addEventListener('message', event => this.handleControlMessage(event));
|
|
104
|
-
this.messageHandlers.forEach(handler => {
|
|
105
|
-
socket.addEventListener('message', handler);
|
|
106
40
|
});
|
|
107
41
|
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
}
|
|
118
|
-
this.needsResubscribe = false;
|
|
119
|
-
this.resubscribeChannels();
|
|
120
|
-
}
|
|
121
|
-
}, {
|
|
122
|
-
key: "handleControlMessage",
|
|
123
|
-
value: function handleControlMessage(event) {
|
|
124
|
-
let data;
|
|
125
|
-
try {
|
|
126
|
-
data = JSON.parse(event.data);
|
|
127
|
-
} catch {
|
|
128
|
-
return;
|
|
129
|
-
}
|
|
130
|
-
if (data.type !== 'confirm_subscription') {
|
|
42
|
+
}
|
|
43
|
+
onMessage(callback) {
|
|
44
|
+
const handler = event => {
|
|
45
|
+
const data = JSON.parse(event.data);
|
|
46
|
+
const {
|
|
47
|
+
type,
|
|
48
|
+
message
|
|
49
|
+
} = data;
|
|
50
|
+
if (this.ignoredEvents.includes(type)) {
|
|
131
51
|
return;
|
|
132
52
|
}
|
|
133
|
-
|
|
53
|
+
callback(message);
|
|
54
|
+
};
|
|
55
|
+
ApplicationChannel.messageHandlers.add(handler);
|
|
56
|
+
ApplicationChannel.ensureWebSocket().addEventListener('message', handler);
|
|
57
|
+
}
|
|
58
|
+
onDisconnect(callback) {
|
|
59
|
+
ApplicationChannel.disconnectHandlers.add(callback);
|
|
60
|
+
}
|
|
61
|
+
onSubscriptionConfirmed(callback) {
|
|
62
|
+
ApplicationChannel.subscriptionConfirmHandlers.add(callback);
|
|
63
|
+
}
|
|
64
|
+
get webSocket() {
|
|
65
|
+
return ApplicationChannel.ensureWebSocket();
|
|
66
|
+
}
|
|
67
|
+
static ensureWebSocket() {
|
|
68
|
+
if (this.webSocket && !this.closedWebSocket(this.webSocket)) {
|
|
69
|
+
return this.webSocket;
|
|
134
70
|
}
|
|
135
|
-
|
|
136
|
-
key: "handleDisconnect",
|
|
137
|
-
value: function handleDisconnect(socket) {
|
|
138
|
-
if (socket !== this.webSocket) {
|
|
139
|
-
return;
|
|
140
|
-
}
|
|
141
|
-
this.disconnectHandlers.forEach(callback => callback());
|
|
142
|
-
this.webSocket = null;
|
|
71
|
+
if (this.webSocket) {
|
|
143
72
|
this.needsResubscribe = true;
|
|
144
|
-
this.scheduleReconnect();
|
|
145
73
|
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
74
|
+
return this.openWebSocket();
|
|
75
|
+
}
|
|
76
|
+
static openWebSocket() {
|
|
77
|
+
this.clearReconnectTimeout();
|
|
78
|
+
const socket = new WebSocket(_core.Configuration.actionCableUrl);
|
|
79
|
+
this.webSocket = socket;
|
|
80
|
+
this.installWebSocketHandlers(socket);
|
|
81
|
+
return socket;
|
|
82
|
+
}
|
|
83
|
+
static installWebSocketHandlers(socket) {
|
|
84
|
+
socket.addEventListener('open', () => this.handleOpen(socket));
|
|
85
|
+
socket.addEventListener('close', () => this.handleDisconnect(socket));
|
|
86
|
+
socket.addEventListener('error', () => this.handleDisconnect(socket));
|
|
87
|
+
socket.addEventListener('message', event => this.handleControlMessage(event));
|
|
88
|
+
this.messageHandlers.forEach(handler => {
|
|
89
|
+
socket.addEventListener('message', handler);
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
static handleOpen(socket) {
|
|
93
|
+
if (socket !== this.webSocket) {
|
|
94
|
+
return;
|
|
157
95
|
}
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
if (this.reconnectTimeout) {
|
|
162
|
-
clearTimeout(this.reconnectTimeout);
|
|
163
|
-
this.reconnectTimeout = null;
|
|
164
|
-
}
|
|
96
|
+
this.reconnectAttempts = 0;
|
|
97
|
+
if (!this.needsResubscribe) {
|
|
98
|
+
return;
|
|
165
99
|
}
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
100
|
+
this.needsResubscribe = false;
|
|
101
|
+
this.resubscribeChannels();
|
|
102
|
+
}
|
|
103
|
+
static handleControlMessage(event) {
|
|
104
|
+
let data;
|
|
105
|
+
try {
|
|
106
|
+
data = JSON.parse(event.data);
|
|
107
|
+
} catch {
|
|
108
|
+
return;
|
|
175
109
|
}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
value: function closedWebSocket(socket) {
|
|
179
|
-
return socket.readyState === WebSocket.CLOSED || socket.readyState === WebSocket.CLOSING;
|
|
110
|
+
if (data.type !== 'confirm_subscription') {
|
|
111
|
+
return;
|
|
180
112
|
}
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
113
|
+
this.subscriptionConfirmHandlers.forEach(callback => callback(data.identifier));
|
|
114
|
+
}
|
|
115
|
+
static handleDisconnect(socket) {
|
|
116
|
+
if (socket !== this.webSocket) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
this.disconnectHandlers.forEach(callback => callback());
|
|
120
|
+
this.webSocket = null;
|
|
121
|
+
this.needsResubscribe = true;
|
|
122
|
+
this.scheduleReconnect();
|
|
123
|
+
}
|
|
124
|
+
static scheduleReconnect() {
|
|
125
|
+
if (this.reconnectTimeout) {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
this.reconnectTimeout = setTimeout(() => {
|
|
129
|
+
this.reconnectTimeout = null;
|
|
130
|
+
this.reconnectAttempts += 1;
|
|
131
|
+
this.openWebSocket();
|
|
132
|
+
}, this.reconnectDelay);
|
|
133
|
+
}
|
|
134
|
+
static clearReconnectTimeout() {
|
|
135
|
+
if (this.reconnectTimeout) {
|
|
136
|
+
clearTimeout(this.reconnectTimeout);
|
|
137
|
+
this.reconnectTimeout = null;
|
|
187
138
|
}
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
139
|
+
}
|
|
140
|
+
static resubscribeChannels() {
|
|
141
|
+
this.channels.forEach(channel => {
|
|
142
|
+
const resubscribe = channel.resubscribe || channel.subscribe;
|
|
143
|
+
if (typeof resubscribe === 'function') {
|
|
144
|
+
resubscribe.call(channel);
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
static closedWebSocket(socket) {
|
|
149
|
+
return socket.readyState === WebSocket.CLOSED || socket.readyState === WebSocket.CLOSING;
|
|
150
|
+
}
|
|
151
|
+
static get reconnectDelay() {
|
|
152
|
+
const delay = Math.min(this.reconnectMaxDelay, this.reconnectBaseDelay * 2 ** this.reconnectAttempts);
|
|
153
|
+
const jitter = Math.round(delay * this.reconnectJitter * Math.random());
|
|
154
|
+
return delay + jitter;
|
|
155
|
+
}
|
|
156
|
+
get ignoredEvents() {
|
|
157
|
+
return ['ping', 'confirm_subscription', 'welcome'];
|
|
158
|
+
}
|
|
159
|
+
}
|
|
202
160
|
var _default = ApplicationChannel;
|
|
203
161
|
exports.default = _default;
|
|
@@ -1,197 +1,154 @@
|
|
|
1
|
-
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
2
|
-
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
|
|
3
|
-
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
|
|
4
|
-
function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
|
|
5
|
-
function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
|
|
6
1
|
import { Configuration } from '../core';
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
2
|
+
class ApplicationChannel {
|
|
3
|
+
static webSocket;
|
|
4
|
+
static channels = new Set();
|
|
5
|
+
static messageHandlers = new Set();
|
|
6
|
+
static disconnectHandlers = new Set();
|
|
7
|
+
static subscriptionConfirmHandlers = new Set();
|
|
8
|
+
static reconnectTimeout = null;
|
|
9
|
+
static reconnectAttempts = 0;
|
|
10
|
+
static reconnectBaseDelay = 500;
|
|
11
|
+
static reconnectMaxDelay = 10000;
|
|
12
|
+
static reconnectJitter = 0.3;
|
|
13
|
+
static needsResubscribe = false;
|
|
14
|
+
constructor() {
|
|
10
15
|
ApplicationChannel.channels.add(this);
|
|
11
16
|
}
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
17
|
+
send({
|
|
18
|
+
command,
|
|
19
|
+
identifier,
|
|
20
|
+
data
|
|
21
|
+
}) {
|
|
22
|
+
const payload = {
|
|
23
|
+
command,
|
|
24
|
+
identifier: JSON.stringify(identifier),
|
|
25
|
+
data: JSON.stringify(data || {})
|
|
26
|
+
};
|
|
27
|
+
const socket = ApplicationChannel.ensureWebSocket();
|
|
28
|
+
const message = JSON.stringify(payload);
|
|
29
|
+
if (socket.readyState === WebSocket.OPEN) {
|
|
30
|
+
socket.send(message);
|
|
31
|
+
} else {
|
|
32
|
+
socket.addEventListener('open', () => {
|
|
28
33
|
socket.send(message);
|
|
29
|
-
} else {
|
|
30
|
-
socket.addEventListener('open', () => {
|
|
31
|
-
socket.send(message);
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
}, {
|
|
36
|
-
key: "onMessage",
|
|
37
|
-
value: function onMessage(callback) {
|
|
38
|
-
var handler = event => {
|
|
39
|
-
var data = JSON.parse(event.data);
|
|
40
|
-
var {
|
|
41
|
-
type,
|
|
42
|
-
message
|
|
43
|
-
} = data;
|
|
44
|
-
if (this.ignoredEvents.includes(type)) {
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
callback(message);
|
|
48
|
-
};
|
|
49
|
-
ApplicationChannel.messageHandlers.add(handler);
|
|
50
|
-
ApplicationChannel.ensureWebSocket().addEventListener('message', handler);
|
|
51
|
-
}
|
|
52
|
-
}, {
|
|
53
|
-
key: "onDisconnect",
|
|
54
|
-
value: function onDisconnect(callback) {
|
|
55
|
-
ApplicationChannel.disconnectHandlers.add(callback);
|
|
56
|
-
}
|
|
57
|
-
}, {
|
|
58
|
-
key: "onSubscriptionConfirmed",
|
|
59
|
-
value: function onSubscriptionConfirmed(callback) {
|
|
60
|
-
ApplicationChannel.subscriptionConfirmHandlers.add(callback);
|
|
61
|
-
}
|
|
62
|
-
}, {
|
|
63
|
-
key: "webSocket",
|
|
64
|
-
get: function get() {
|
|
65
|
-
return ApplicationChannel.ensureWebSocket();
|
|
66
|
-
}
|
|
67
|
-
}, {
|
|
68
|
-
key: "ignoredEvents",
|
|
69
|
-
get: function get() {
|
|
70
|
-
return ['ping', 'confirm_subscription', 'welcome'];
|
|
71
|
-
}
|
|
72
|
-
}], [{
|
|
73
|
-
key: "ensureWebSocket",
|
|
74
|
-
value: function ensureWebSocket() {
|
|
75
|
-
if (this.webSocket && !this.closedWebSocket(this.webSocket)) {
|
|
76
|
-
return this.webSocket;
|
|
77
|
-
}
|
|
78
|
-
if (this.webSocket) {
|
|
79
|
-
this.needsResubscribe = true;
|
|
80
|
-
}
|
|
81
|
-
return this.openWebSocket();
|
|
82
|
-
}
|
|
83
|
-
}, {
|
|
84
|
-
key: "openWebSocket",
|
|
85
|
-
value: function openWebSocket() {
|
|
86
|
-
this.clearReconnectTimeout();
|
|
87
|
-
var socket = new WebSocket(Configuration.actionCableUrl);
|
|
88
|
-
this.webSocket = socket;
|
|
89
|
-
this.installWebSocketHandlers(socket);
|
|
90
|
-
return socket;
|
|
91
|
-
}
|
|
92
|
-
}, {
|
|
93
|
-
key: "installWebSocketHandlers",
|
|
94
|
-
value: function installWebSocketHandlers(socket) {
|
|
95
|
-
socket.addEventListener('open', () => this.handleOpen(socket));
|
|
96
|
-
socket.addEventListener('close', () => this.handleDisconnect(socket));
|
|
97
|
-
socket.addEventListener('error', () => this.handleDisconnect(socket));
|
|
98
|
-
socket.addEventListener('message', event => this.handleControlMessage(event));
|
|
99
|
-
this.messageHandlers.forEach(handler => {
|
|
100
|
-
socket.addEventListener('message', handler);
|
|
101
34
|
});
|
|
102
35
|
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
}
|
|
113
|
-
this.needsResubscribe = false;
|
|
114
|
-
this.resubscribeChannels();
|
|
115
|
-
}
|
|
116
|
-
}, {
|
|
117
|
-
key: "handleControlMessage",
|
|
118
|
-
value: function handleControlMessage(event) {
|
|
119
|
-
var data;
|
|
120
|
-
try {
|
|
121
|
-
data = JSON.parse(event.data);
|
|
122
|
-
} catch (_unused) {
|
|
123
|
-
return;
|
|
124
|
-
}
|
|
125
|
-
if (data.type !== 'confirm_subscription') {
|
|
36
|
+
}
|
|
37
|
+
onMessage(callback) {
|
|
38
|
+
const handler = event => {
|
|
39
|
+
const data = JSON.parse(event.data);
|
|
40
|
+
const {
|
|
41
|
+
type,
|
|
42
|
+
message
|
|
43
|
+
} = data;
|
|
44
|
+
if (this.ignoredEvents.includes(type)) {
|
|
126
45
|
return;
|
|
127
46
|
}
|
|
128
|
-
|
|
47
|
+
callback(message);
|
|
48
|
+
};
|
|
49
|
+
ApplicationChannel.messageHandlers.add(handler);
|
|
50
|
+
ApplicationChannel.ensureWebSocket().addEventListener('message', handler);
|
|
51
|
+
}
|
|
52
|
+
onDisconnect(callback) {
|
|
53
|
+
ApplicationChannel.disconnectHandlers.add(callback);
|
|
54
|
+
}
|
|
55
|
+
onSubscriptionConfirmed(callback) {
|
|
56
|
+
ApplicationChannel.subscriptionConfirmHandlers.add(callback);
|
|
57
|
+
}
|
|
58
|
+
get webSocket() {
|
|
59
|
+
return ApplicationChannel.ensureWebSocket();
|
|
60
|
+
}
|
|
61
|
+
static ensureWebSocket() {
|
|
62
|
+
if (this.webSocket && !this.closedWebSocket(this.webSocket)) {
|
|
63
|
+
return this.webSocket;
|
|
129
64
|
}
|
|
130
|
-
|
|
131
|
-
key: "handleDisconnect",
|
|
132
|
-
value: function handleDisconnect(socket) {
|
|
133
|
-
if (socket !== this.webSocket) {
|
|
134
|
-
return;
|
|
135
|
-
}
|
|
136
|
-
this.disconnectHandlers.forEach(callback => callback());
|
|
137
|
-
this.webSocket = null;
|
|
65
|
+
if (this.webSocket) {
|
|
138
66
|
this.needsResubscribe = true;
|
|
139
|
-
this.scheduleReconnect();
|
|
140
67
|
}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
68
|
+
return this.openWebSocket();
|
|
69
|
+
}
|
|
70
|
+
static openWebSocket() {
|
|
71
|
+
this.clearReconnectTimeout();
|
|
72
|
+
const socket = new WebSocket(Configuration.actionCableUrl);
|
|
73
|
+
this.webSocket = socket;
|
|
74
|
+
this.installWebSocketHandlers(socket);
|
|
75
|
+
return socket;
|
|
76
|
+
}
|
|
77
|
+
static installWebSocketHandlers(socket) {
|
|
78
|
+
socket.addEventListener('open', () => this.handleOpen(socket));
|
|
79
|
+
socket.addEventListener('close', () => this.handleDisconnect(socket));
|
|
80
|
+
socket.addEventListener('error', () => this.handleDisconnect(socket));
|
|
81
|
+
socket.addEventListener('message', event => this.handleControlMessage(event));
|
|
82
|
+
this.messageHandlers.forEach(handler => {
|
|
83
|
+
socket.addEventListener('message', handler);
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
static handleOpen(socket) {
|
|
87
|
+
if (socket !== this.webSocket) {
|
|
88
|
+
return;
|
|
152
89
|
}
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
if (this.reconnectTimeout) {
|
|
157
|
-
clearTimeout(this.reconnectTimeout);
|
|
158
|
-
this.reconnectTimeout = null;
|
|
159
|
-
}
|
|
90
|
+
this.reconnectAttempts = 0;
|
|
91
|
+
if (!this.needsResubscribe) {
|
|
92
|
+
return;
|
|
160
93
|
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
94
|
+
this.needsResubscribe = false;
|
|
95
|
+
this.resubscribeChannels();
|
|
96
|
+
}
|
|
97
|
+
static handleControlMessage(event) {
|
|
98
|
+
let data;
|
|
99
|
+
try {
|
|
100
|
+
data = JSON.parse(event.data);
|
|
101
|
+
} catch {
|
|
102
|
+
return;
|
|
170
103
|
}
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
value: function closedWebSocket(socket) {
|
|
174
|
-
return socket.readyState === WebSocket.CLOSED || socket.readyState === WebSocket.CLOSING;
|
|
104
|
+
if (data.type !== 'confirm_subscription') {
|
|
105
|
+
return;
|
|
175
106
|
}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
107
|
+
this.subscriptionConfirmHandlers.forEach(callback => callback(data.identifier));
|
|
108
|
+
}
|
|
109
|
+
static handleDisconnect(socket) {
|
|
110
|
+
if (socket !== this.webSocket) {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
this.disconnectHandlers.forEach(callback => callback());
|
|
114
|
+
this.webSocket = null;
|
|
115
|
+
this.needsResubscribe = true;
|
|
116
|
+
this.scheduleReconnect();
|
|
117
|
+
}
|
|
118
|
+
static scheduleReconnect() {
|
|
119
|
+
if (this.reconnectTimeout) {
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
this.reconnectTimeout = setTimeout(() => {
|
|
123
|
+
this.reconnectTimeout = null;
|
|
124
|
+
this.reconnectAttempts += 1;
|
|
125
|
+
this.openWebSocket();
|
|
126
|
+
}, this.reconnectDelay);
|
|
127
|
+
}
|
|
128
|
+
static clearReconnectTimeout() {
|
|
129
|
+
if (this.reconnectTimeout) {
|
|
130
|
+
clearTimeout(this.reconnectTimeout);
|
|
131
|
+
this.reconnectTimeout = null;
|
|
182
132
|
}
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
133
|
+
}
|
|
134
|
+
static resubscribeChannels() {
|
|
135
|
+
this.channels.forEach(channel => {
|
|
136
|
+
const resubscribe = channel.resubscribe || channel.subscribe;
|
|
137
|
+
if (typeof resubscribe === 'function') {
|
|
138
|
+
resubscribe.call(channel);
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
static closedWebSocket(socket) {
|
|
143
|
+
return socket.readyState === WebSocket.CLOSED || socket.readyState === WebSocket.CLOSING;
|
|
144
|
+
}
|
|
145
|
+
static get reconnectDelay() {
|
|
146
|
+
const delay = Math.min(this.reconnectMaxDelay, this.reconnectBaseDelay * 2 ** this.reconnectAttempts);
|
|
147
|
+
const jitter = Math.round(delay * this.reconnectJitter * Math.random());
|
|
148
|
+
return delay + jitter;
|
|
149
|
+
}
|
|
150
|
+
get ignoredEvents() {
|
|
151
|
+
return ['ping', 'confirm_subscription', 'welcome'];
|
|
152
|
+
}
|
|
153
|
+
}
|
|
197
154
|
export default ApplicationChannel;
|