optics_view_components 0.1.8 → 0.1.10
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.
- checksums.yaml +4 -4
- data/Gemfile +2 -0
- data/Gemfile.lock +7 -1
- data/Procfile +1 -0
- data/app/components/optics/sidebar/component.rb +10 -7
- data/config.ru +3 -0
- data/demo/Gemfile +1 -1
- data/demo/Gemfile.lock +7 -4
- data/demo/config/application.rb +2 -1
- data/demo/public/assets/.sprockets-manifest-9054defc6f9a603f4d0efa7eef36e3a7.json +1 -0
- data/demo/public/assets/actioncable-5433453f9b6619a9de91aaab2d7fc7ff183e5260c0107cbc9a1aa0c838d9a74e.js +489 -0
- data/demo/public/assets/actioncable-5433453f9b6619a9de91aaab2d7fc7ff183e5260c0107cbc9a1aa0c838d9a74e.js.gz +0 -0
- data/demo/public/assets/actioncable.esm-e01089c3ec4fe7817fa9abcad06cab6bdc387f95f0ca6aab4bf7ba7537f70690.js +491 -0
- data/demo/public/assets/actioncable.esm-e01089c3ec4fe7817fa9abcad06cab6bdc387f95f0ca6aab4bf7ba7537f70690.js.gz +0 -0
- data/demo/public/assets/application-0637d2874099d8ba663ba7c4b7ae404ed5d14dce524e1199c89ad93f13956807.css +3715 -0
- data/demo/public/assets/application-0637d2874099d8ba663ba7c4b7ae404ed5d14dce524e1199c89ad93f13956807.css.gz +0 -0
- data/demo/public/assets/manifest-dad05bf766af0fe3d79dd746db3c1361c0583026cdf35d6a2921bccaea835331.js +3 -0
- data/demo/public/assets/manifest-dad05bf766af0fe3d79dd746db3c1361c0583026cdf35d6a2921bccaea835331.js.gz +0 -0
- data/lib/optics/view_components/version.rb +1 -1
- data/previews/optics/button_preview/with_icon.html.erb +1 -1
- data/previews/optics/button_preview.rb +1 -1
- metadata +16 -3
- /data/{LICENSE.txt → LICENSE} +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1a951c750d000275cbaab0ba1647db5d7cd22d45b4fd727af9ce8a85ebebfbae
|
4
|
+
data.tar.gz: f26dcc64414812ba6ec93bae0be942b803f2da601876506e23782eaed9084334
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9cc9ad65a1cbdb94c2553d35db1c52f1c11176c75af7ff8064fbd144dc67b80a3d6e90f56615e57c2566b06f90202a16545d313ee6924d7207217171521ff1c8
|
7
|
+
data.tar.gz: 14d71daf38ad04f2cd667ca17aa7e3810e91233c88103d082e4fa7acb0369734fca03b131218367f577bfac54dc10c2844eddd5fa56b5667fa5f07c4aed91e84
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
optics_view_components (0.1.
|
4
|
+
optics_view_components (0.1.9)
|
5
5
|
view_component (> 2.0, < 4.0)
|
6
6
|
|
7
7
|
GEM
|
@@ -138,6 +138,8 @@ GEM
|
|
138
138
|
net-smtp (0.3.3)
|
139
139
|
net-protocol
|
140
140
|
nio4r (2.5.9)
|
141
|
+
nokogiri (1.15.1-arm64-darwin)
|
142
|
+
racc (~> 1.4)
|
141
143
|
nokogiri (1.15.1-x86_64-linux)
|
142
144
|
racc (~> 1.4)
|
143
145
|
parallel (1.23.0)
|
@@ -147,6 +149,8 @@ GEM
|
|
147
149
|
coderay (~> 1.1)
|
148
150
|
method_source (~> 1.0)
|
149
151
|
public_suffix (5.0.1)
|
152
|
+
puma (6.3.1)
|
153
|
+
nio4r (~> 2.0)
|
150
154
|
racc (1.6.2)
|
151
155
|
rack (2.2.7)
|
152
156
|
rack-test (2.1.0)
|
@@ -242,6 +246,7 @@ GEM
|
|
242
246
|
zeitwerk (2.6.8)
|
243
247
|
|
244
248
|
PLATFORMS
|
249
|
+
arm64-darwin-21
|
245
250
|
x86_64-linux
|
246
251
|
|
247
252
|
DEPENDENCIES
|
@@ -250,6 +255,7 @@ DEPENDENCIES
|
|
250
255
|
lookbook
|
251
256
|
optics_view_components!
|
252
257
|
pry
|
258
|
+
puma (~> 6.3)
|
253
259
|
rails (~> 7.0)
|
254
260
|
rake (~> 13.0)
|
255
261
|
rspec (~> 3.0)
|
data/Procfile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
web: bundle exec rackup -p ${PORT:-5000} config.ru
|
@@ -14,7 +14,8 @@ module Optics
|
|
14
14
|
def call
|
15
15
|
content_tag(
|
16
16
|
:nav,
|
17
|
-
class: classes
|
17
|
+
class: classes,
|
18
|
+
**@attributes.except(:class)
|
18
19
|
) do
|
19
20
|
capture do
|
20
21
|
concat brand
|
@@ -40,12 +41,13 @@ module Optics
|
|
40
41
|
|
41
42
|
class Brand < ApplicationViewComponent
|
42
43
|
accepts :url
|
43
|
-
accepts :
|
44
|
+
accepts :image_source
|
45
|
+
accepts :image_label
|
44
46
|
accepts :name
|
45
47
|
|
46
48
|
def call
|
47
|
-
link_to(url, class: 'sidebar__brand') do
|
48
|
-
name || image_tag(
|
49
|
+
link_to(url, class: 'sidebar__brand', **@attributes) do
|
50
|
+
name || image_tag(image_source, alt: image_label)
|
49
51
|
end
|
50
52
|
end
|
51
53
|
end
|
@@ -54,7 +56,7 @@ module Optics
|
|
54
56
|
accepts :position, default: 'center'
|
55
57
|
|
56
58
|
def call
|
57
|
-
content_tag(:div, class: classes) do
|
59
|
+
content_tag(:div, class: classes, **@attributes) do
|
58
60
|
content
|
59
61
|
end
|
60
62
|
end
|
@@ -62,7 +64,8 @@ module Optics
|
|
62
64
|
def classes
|
63
65
|
class_names(
|
64
66
|
'sidebar__content',
|
65
|
-
position_class
|
67
|
+
position_class,
|
68
|
+
@attributes[:class]
|
66
69
|
).join(' ')
|
67
70
|
end
|
68
71
|
|
@@ -76,7 +79,7 @@ module Optics
|
|
76
79
|
accepts :url
|
77
80
|
|
78
81
|
def call
|
79
|
-
link_to(url, class: 'sidebar__brand') do
|
82
|
+
link_to(url, class: 'sidebar__brand', **@attributes) do
|
80
83
|
image_tag(img_src)
|
81
84
|
end
|
82
85
|
end
|
data/config.ru
ADDED
data/demo/Gemfile
CHANGED
data/demo/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: ..
|
3
3
|
specs:
|
4
|
-
optics_view_components (0.1.
|
4
|
+
optics_view_components (0.1.9)
|
5
5
|
view_component (> 2.0, < 4.0)
|
6
6
|
|
7
7
|
GEM
|
@@ -133,10 +133,12 @@ GEM
|
|
133
133
|
net-smtp (0.3.3)
|
134
134
|
net-protocol
|
135
135
|
nio4r (2.5.9)
|
136
|
-
nokogiri (1.15.
|
136
|
+
nokogiri (1.15.3-arm64-darwin)
|
137
|
+
racc (~> 1.4)
|
138
|
+
nokogiri (1.15.3-x86_64-linux)
|
137
139
|
racc (~> 1.4)
|
138
140
|
public_suffix (5.0.1)
|
139
|
-
puma (6.
|
141
|
+
puma (6.3.1)
|
140
142
|
nio4r (~> 2.0)
|
141
143
|
racc (1.6.2)
|
142
144
|
rack (2.2.7)
|
@@ -200,6 +202,7 @@ GEM
|
|
200
202
|
zeitwerk (2.6.8)
|
201
203
|
|
202
204
|
PLATFORMS
|
205
|
+
arm64-darwin-22
|
203
206
|
x86_64-linux
|
204
207
|
|
205
208
|
DEPENDENCIES
|
@@ -208,7 +211,7 @@ DEPENDENCIES
|
|
208
211
|
debug
|
209
212
|
lookbook
|
210
213
|
optics_view_components!
|
211
|
-
puma (~> 6.
|
214
|
+
puma (~> 6.3)
|
212
215
|
rails (~> 7.0.4, >= 7.0.4.3)
|
213
216
|
sprockets-rails
|
214
217
|
web-console
|
data/demo/config/application.rb
CHANGED
@@ -25,8 +25,9 @@ module Demo
|
|
25
25
|
config.load_defaults 7.0
|
26
26
|
|
27
27
|
config.view_component.default_preview_layout = 'preview'
|
28
|
-
config.view_component.preview_paths
|
28
|
+
config.view_component.preview_paths = [Optics::ViewComponents::Engine.root.join('previews')]
|
29
29
|
config.lookbook.project_name = "Optics ViewComponents v#{Optics::ViewComponents::VERSION}"
|
30
30
|
config.lookbook.component_paths = [Optics::ViewComponents::Engine.root.join('app', 'components')]
|
31
|
+
config.view_component.show_previews = true
|
31
32
|
end
|
32
33
|
end
|
@@ -0,0 +1 @@
|
|
1
|
+
{"files":{"manifest-dad05bf766af0fe3d79dd746db3c1361c0583026cdf35d6a2921bccaea835331.js":{"logical_path":"manifest.js","mtime":"2023-07-21T16:26:54-04:00","size":3,"digest":"6a3cf5192354f71615ac51034b3e97c20eda99643fcaf5bbe6d41ad59bd12167","integrity":"sha256-ajz1GSNU9xYVrFEDSz6Xwg7amWQ/yvW75tQa1ZvRIWc="},"application-0637d2874099d8ba663ba7c4b7ae404ed5d14dce524e1199c89ad93f13956807.css":{"logical_path":"application.css","mtime":"2023-07-21T16:26:54-04:00","size":191384,"digest":"804e47b010668b842d5c04f570a7a3a8346cb83928c31ebb7d08b3c9c0b4417b","integrity":"sha256-gE5HsBBmi4QtXAT1cKejqDRsuDkowx67fQizycC0QXs="},"actioncable-5433453f9b6619a9de91aaab2d7fc7ff183e5260c0107cbc9a1aa0c838d9a74e.js":{"logical_path":"actioncable.js","mtime":"2023-07-21T16:26:54-04:00","size":15699,"digest":"6b2fe44d9e4546fcc6b92f0a37b61d6b555020041ede1dd603c007b1c0904ec1","integrity":"sha256-ay/kTZ5FRvzGuS8KN7Yda1VQIAQe3h3WA8AHscCQTsE="},"actioncable.esm-e01089c3ec4fe7817fa9abcad06cab6bdc387f95f0ca6aab4bf7ba7537f70690.js":{"logical_path":"actioncable.esm.js","mtime":"2023-07-21T16:26:54-04:00","size":14080,"digest":"a9e53dfa810276aa0aee8791a910c4878d48b75093398f3d6d822db41b428b7b","integrity":"sha256-qeU9+oECdqoK7oeRqRDEh41It1CTOY89bYIttBtCi3s="}},"assets":{"manifest.js":"manifest-dad05bf766af0fe3d79dd746db3c1361c0583026cdf35d6a2921bccaea835331.js","application.css":"application-0637d2874099d8ba663ba7c4b7ae404ed5d14dce524e1199c89ad93f13956807.css","actioncable.js":"actioncable-5433453f9b6619a9de91aaab2d7fc7ff183e5260c0107cbc9a1aa0c838d9a74e.js","actioncable.esm.js":"actioncable.esm-e01089c3ec4fe7817fa9abcad06cab6bdc387f95f0ca6aab4bf7ba7537f70690.js"}}
|
@@ -0,0 +1,489 @@
|
|
1
|
+
(function(global, factory) {
|
2
|
+
typeof exports === "object" && typeof module !== "undefined" ? factory(exports) : typeof define === "function" && define.amd ? define([ "exports" ], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self,
|
3
|
+
factory(global.ActionCable = {}));
|
4
|
+
})(this, (function(exports) {
|
5
|
+
"use strict";
|
6
|
+
var adapters = {
|
7
|
+
logger: self.console,
|
8
|
+
WebSocket: self.WebSocket
|
9
|
+
};
|
10
|
+
var logger = {
|
11
|
+
log(...messages) {
|
12
|
+
if (this.enabled) {
|
13
|
+
messages.push(Date.now());
|
14
|
+
adapters.logger.log("[ActionCable]", ...messages);
|
15
|
+
}
|
16
|
+
}
|
17
|
+
};
|
18
|
+
const now = () => (new Date).getTime();
|
19
|
+
const secondsSince = time => (now() - time) / 1e3;
|
20
|
+
class ConnectionMonitor {
|
21
|
+
constructor(connection) {
|
22
|
+
this.visibilityDidChange = this.visibilityDidChange.bind(this);
|
23
|
+
this.connection = connection;
|
24
|
+
this.reconnectAttempts = 0;
|
25
|
+
}
|
26
|
+
start() {
|
27
|
+
if (!this.isRunning()) {
|
28
|
+
this.startedAt = now();
|
29
|
+
delete this.stoppedAt;
|
30
|
+
this.startPolling();
|
31
|
+
addEventListener("visibilitychange", this.visibilityDidChange);
|
32
|
+
logger.log(`ConnectionMonitor started. stale threshold = ${this.constructor.staleThreshold} s`);
|
33
|
+
}
|
34
|
+
}
|
35
|
+
stop() {
|
36
|
+
if (this.isRunning()) {
|
37
|
+
this.stoppedAt = now();
|
38
|
+
this.stopPolling();
|
39
|
+
removeEventListener("visibilitychange", this.visibilityDidChange);
|
40
|
+
logger.log("ConnectionMonitor stopped");
|
41
|
+
}
|
42
|
+
}
|
43
|
+
isRunning() {
|
44
|
+
return this.startedAt && !this.stoppedAt;
|
45
|
+
}
|
46
|
+
recordPing() {
|
47
|
+
this.pingedAt = now();
|
48
|
+
}
|
49
|
+
recordConnect() {
|
50
|
+
this.reconnectAttempts = 0;
|
51
|
+
this.recordPing();
|
52
|
+
delete this.disconnectedAt;
|
53
|
+
logger.log("ConnectionMonitor recorded connect");
|
54
|
+
}
|
55
|
+
recordDisconnect() {
|
56
|
+
this.disconnectedAt = now();
|
57
|
+
logger.log("ConnectionMonitor recorded disconnect");
|
58
|
+
}
|
59
|
+
startPolling() {
|
60
|
+
this.stopPolling();
|
61
|
+
this.poll();
|
62
|
+
}
|
63
|
+
stopPolling() {
|
64
|
+
clearTimeout(this.pollTimeout);
|
65
|
+
}
|
66
|
+
poll() {
|
67
|
+
this.pollTimeout = setTimeout((() => {
|
68
|
+
this.reconnectIfStale();
|
69
|
+
this.poll();
|
70
|
+
}), this.getPollInterval());
|
71
|
+
}
|
72
|
+
getPollInterval() {
|
73
|
+
const {staleThreshold: staleThreshold, reconnectionBackoffRate: reconnectionBackoffRate} = this.constructor;
|
74
|
+
const backoff = Math.pow(1 + reconnectionBackoffRate, Math.min(this.reconnectAttempts, 10));
|
75
|
+
const jitterMax = this.reconnectAttempts === 0 ? 1 : reconnectionBackoffRate;
|
76
|
+
const jitter = jitterMax * Math.random();
|
77
|
+
return staleThreshold * 1e3 * backoff * (1 + jitter);
|
78
|
+
}
|
79
|
+
reconnectIfStale() {
|
80
|
+
if (this.connectionIsStale()) {
|
81
|
+
logger.log(`ConnectionMonitor detected stale connection. reconnectAttempts = ${this.reconnectAttempts}, time stale = ${secondsSince(this.refreshedAt)} s, stale threshold = ${this.constructor.staleThreshold} s`);
|
82
|
+
this.reconnectAttempts++;
|
83
|
+
if (this.disconnectedRecently()) {
|
84
|
+
logger.log(`ConnectionMonitor skipping reopening recent disconnect. time disconnected = ${secondsSince(this.disconnectedAt)} s`);
|
85
|
+
} else {
|
86
|
+
logger.log("ConnectionMonitor reopening");
|
87
|
+
this.connection.reopen();
|
88
|
+
}
|
89
|
+
}
|
90
|
+
}
|
91
|
+
get refreshedAt() {
|
92
|
+
return this.pingedAt ? this.pingedAt : this.startedAt;
|
93
|
+
}
|
94
|
+
connectionIsStale() {
|
95
|
+
return secondsSince(this.refreshedAt) > this.constructor.staleThreshold;
|
96
|
+
}
|
97
|
+
disconnectedRecently() {
|
98
|
+
return this.disconnectedAt && secondsSince(this.disconnectedAt) < this.constructor.staleThreshold;
|
99
|
+
}
|
100
|
+
visibilityDidChange() {
|
101
|
+
if (document.visibilityState === "visible") {
|
102
|
+
setTimeout((() => {
|
103
|
+
if (this.connectionIsStale() || !this.connection.isOpen()) {
|
104
|
+
logger.log(`ConnectionMonitor reopening stale connection on visibilitychange. visibilityState = ${document.visibilityState}`);
|
105
|
+
this.connection.reopen();
|
106
|
+
}
|
107
|
+
}), 200);
|
108
|
+
}
|
109
|
+
}
|
110
|
+
}
|
111
|
+
ConnectionMonitor.staleThreshold = 6;
|
112
|
+
ConnectionMonitor.reconnectionBackoffRate = .15;
|
113
|
+
var INTERNAL = {
|
114
|
+
message_types: {
|
115
|
+
welcome: "welcome",
|
116
|
+
disconnect: "disconnect",
|
117
|
+
ping: "ping",
|
118
|
+
confirmation: "confirm_subscription",
|
119
|
+
rejection: "reject_subscription"
|
120
|
+
},
|
121
|
+
disconnect_reasons: {
|
122
|
+
unauthorized: "unauthorized",
|
123
|
+
invalid_request: "invalid_request",
|
124
|
+
server_restart: "server_restart"
|
125
|
+
},
|
126
|
+
default_mount_path: "/cable",
|
127
|
+
protocols: [ "actioncable-v1-json", "actioncable-unsupported" ]
|
128
|
+
};
|
129
|
+
const {message_types: message_types, protocols: protocols} = INTERNAL;
|
130
|
+
const supportedProtocols = protocols.slice(0, protocols.length - 1);
|
131
|
+
const indexOf = [].indexOf;
|
132
|
+
class Connection {
|
133
|
+
constructor(consumer) {
|
134
|
+
this.open = this.open.bind(this);
|
135
|
+
this.consumer = consumer;
|
136
|
+
this.subscriptions = this.consumer.subscriptions;
|
137
|
+
this.monitor = new ConnectionMonitor(this);
|
138
|
+
this.disconnected = true;
|
139
|
+
}
|
140
|
+
send(data) {
|
141
|
+
if (this.isOpen()) {
|
142
|
+
this.webSocket.send(JSON.stringify(data));
|
143
|
+
return true;
|
144
|
+
} else {
|
145
|
+
return false;
|
146
|
+
}
|
147
|
+
}
|
148
|
+
open() {
|
149
|
+
if (this.isActive()) {
|
150
|
+
logger.log(`Attempted to open WebSocket, but existing socket is ${this.getState()}`);
|
151
|
+
return false;
|
152
|
+
} else {
|
153
|
+
logger.log(`Opening WebSocket, current state is ${this.getState()}, subprotocols: ${protocols}`);
|
154
|
+
if (this.webSocket) {
|
155
|
+
this.uninstallEventHandlers();
|
156
|
+
}
|
157
|
+
this.webSocket = new adapters.WebSocket(this.consumer.url, protocols);
|
158
|
+
this.installEventHandlers();
|
159
|
+
this.monitor.start();
|
160
|
+
return true;
|
161
|
+
}
|
162
|
+
}
|
163
|
+
close({allowReconnect: allowReconnect} = {
|
164
|
+
allowReconnect: true
|
165
|
+
}) {
|
166
|
+
if (!allowReconnect) {
|
167
|
+
this.monitor.stop();
|
168
|
+
}
|
169
|
+
if (this.isOpen()) {
|
170
|
+
return this.webSocket.close();
|
171
|
+
}
|
172
|
+
}
|
173
|
+
reopen() {
|
174
|
+
logger.log(`Reopening WebSocket, current state is ${this.getState()}`);
|
175
|
+
if (this.isActive()) {
|
176
|
+
try {
|
177
|
+
return this.close();
|
178
|
+
} catch (error) {
|
179
|
+
logger.log("Failed to reopen WebSocket", error);
|
180
|
+
} finally {
|
181
|
+
logger.log(`Reopening WebSocket in ${this.constructor.reopenDelay}ms`);
|
182
|
+
setTimeout(this.open, this.constructor.reopenDelay);
|
183
|
+
}
|
184
|
+
} else {
|
185
|
+
return this.open();
|
186
|
+
}
|
187
|
+
}
|
188
|
+
getProtocol() {
|
189
|
+
if (this.webSocket) {
|
190
|
+
return this.webSocket.protocol;
|
191
|
+
}
|
192
|
+
}
|
193
|
+
isOpen() {
|
194
|
+
return this.isState("open");
|
195
|
+
}
|
196
|
+
isActive() {
|
197
|
+
return this.isState("open", "connecting");
|
198
|
+
}
|
199
|
+
isProtocolSupported() {
|
200
|
+
return indexOf.call(supportedProtocols, this.getProtocol()) >= 0;
|
201
|
+
}
|
202
|
+
isState(...states) {
|
203
|
+
return indexOf.call(states, this.getState()) >= 0;
|
204
|
+
}
|
205
|
+
getState() {
|
206
|
+
if (this.webSocket) {
|
207
|
+
for (let state in adapters.WebSocket) {
|
208
|
+
if (adapters.WebSocket[state] === this.webSocket.readyState) {
|
209
|
+
return state.toLowerCase();
|
210
|
+
}
|
211
|
+
}
|
212
|
+
}
|
213
|
+
return null;
|
214
|
+
}
|
215
|
+
installEventHandlers() {
|
216
|
+
for (let eventName in this.events) {
|
217
|
+
const handler = this.events[eventName].bind(this);
|
218
|
+
this.webSocket[`on${eventName}`] = handler;
|
219
|
+
}
|
220
|
+
}
|
221
|
+
uninstallEventHandlers() {
|
222
|
+
for (let eventName in this.events) {
|
223
|
+
this.webSocket[`on${eventName}`] = function() {};
|
224
|
+
}
|
225
|
+
}
|
226
|
+
}
|
227
|
+
Connection.reopenDelay = 500;
|
228
|
+
Connection.prototype.events = {
|
229
|
+
message(event) {
|
230
|
+
if (!this.isProtocolSupported()) {
|
231
|
+
return;
|
232
|
+
}
|
233
|
+
const {identifier: identifier, message: message, reason: reason, reconnect: reconnect, type: type} = JSON.parse(event.data);
|
234
|
+
switch (type) {
|
235
|
+
case message_types.welcome:
|
236
|
+
this.monitor.recordConnect();
|
237
|
+
return this.subscriptions.reload();
|
238
|
+
|
239
|
+
case message_types.disconnect:
|
240
|
+
logger.log(`Disconnecting. Reason: ${reason}`);
|
241
|
+
return this.close({
|
242
|
+
allowReconnect: reconnect
|
243
|
+
});
|
244
|
+
|
245
|
+
case message_types.ping:
|
246
|
+
return this.monitor.recordPing();
|
247
|
+
|
248
|
+
case message_types.confirmation:
|
249
|
+
this.subscriptions.confirmSubscription(identifier);
|
250
|
+
return this.subscriptions.notify(identifier, "connected");
|
251
|
+
|
252
|
+
case message_types.rejection:
|
253
|
+
return this.subscriptions.reject(identifier);
|
254
|
+
|
255
|
+
default:
|
256
|
+
return this.subscriptions.notify(identifier, "received", message);
|
257
|
+
}
|
258
|
+
},
|
259
|
+
open() {
|
260
|
+
logger.log(`WebSocket onopen event, using '${this.getProtocol()}' subprotocol`);
|
261
|
+
this.disconnected = false;
|
262
|
+
if (!this.isProtocolSupported()) {
|
263
|
+
logger.log("Protocol is unsupported. Stopping monitor and disconnecting.");
|
264
|
+
return this.close({
|
265
|
+
allowReconnect: false
|
266
|
+
});
|
267
|
+
}
|
268
|
+
},
|
269
|
+
close(event) {
|
270
|
+
logger.log("WebSocket onclose event");
|
271
|
+
if (this.disconnected) {
|
272
|
+
return;
|
273
|
+
}
|
274
|
+
this.disconnected = true;
|
275
|
+
this.monitor.recordDisconnect();
|
276
|
+
return this.subscriptions.notifyAll("disconnected", {
|
277
|
+
willAttemptReconnect: this.monitor.isRunning()
|
278
|
+
});
|
279
|
+
},
|
280
|
+
error() {
|
281
|
+
logger.log("WebSocket onerror event");
|
282
|
+
}
|
283
|
+
};
|
284
|
+
const extend = function(object, properties) {
|
285
|
+
if (properties != null) {
|
286
|
+
for (let key in properties) {
|
287
|
+
const value = properties[key];
|
288
|
+
object[key] = value;
|
289
|
+
}
|
290
|
+
}
|
291
|
+
return object;
|
292
|
+
};
|
293
|
+
class Subscription {
|
294
|
+
constructor(consumer, params = {}, mixin) {
|
295
|
+
this.consumer = consumer;
|
296
|
+
this.identifier = JSON.stringify(params);
|
297
|
+
extend(this, mixin);
|
298
|
+
}
|
299
|
+
perform(action, data = {}) {
|
300
|
+
data.action = action;
|
301
|
+
return this.send(data);
|
302
|
+
}
|
303
|
+
send(data) {
|
304
|
+
return this.consumer.send({
|
305
|
+
command: "message",
|
306
|
+
identifier: this.identifier,
|
307
|
+
data: JSON.stringify(data)
|
308
|
+
});
|
309
|
+
}
|
310
|
+
unsubscribe() {
|
311
|
+
return this.consumer.subscriptions.remove(this);
|
312
|
+
}
|
313
|
+
}
|
314
|
+
class SubscriptionGuarantor {
|
315
|
+
constructor(subscriptions) {
|
316
|
+
this.subscriptions = subscriptions;
|
317
|
+
this.pendingSubscriptions = [];
|
318
|
+
}
|
319
|
+
guarantee(subscription) {
|
320
|
+
if (this.pendingSubscriptions.indexOf(subscription) == -1) {
|
321
|
+
logger.log(`SubscriptionGuarantor guaranteeing ${subscription.identifier}`);
|
322
|
+
this.pendingSubscriptions.push(subscription);
|
323
|
+
} else {
|
324
|
+
logger.log(`SubscriptionGuarantor already guaranteeing ${subscription.identifier}`);
|
325
|
+
}
|
326
|
+
this.startGuaranteeing();
|
327
|
+
}
|
328
|
+
forget(subscription) {
|
329
|
+
logger.log(`SubscriptionGuarantor forgetting ${subscription.identifier}`);
|
330
|
+
this.pendingSubscriptions = this.pendingSubscriptions.filter((s => s !== subscription));
|
331
|
+
}
|
332
|
+
startGuaranteeing() {
|
333
|
+
this.stopGuaranteeing();
|
334
|
+
this.retrySubscribing();
|
335
|
+
}
|
336
|
+
stopGuaranteeing() {
|
337
|
+
clearTimeout(this.retryTimeout);
|
338
|
+
}
|
339
|
+
retrySubscribing() {
|
340
|
+
this.retryTimeout = setTimeout((() => {
|
341
|
+
if (this.subscriptions && typeof this.subscriptions.subscribe === "function") {
|
342
|
+
this.pendingSubscriptions.map((subscription => {
|
343
|
+
logger.log(`SubscriptionGuarantor resubscribing ${subscription.identifier}`);
|
344
|
+
this.subscriptions.subscribe(subscription);
|
345
|
+
}));
|
346
|
+
}
|
347
|
+
}), 500);
|
348
|
+
}
|
349
|
+
}
|
350
|
+
class Subscriptions {
|
351
|
+
constructor(consumer) {
|
352
|
+
this.consumer = consumer;
|
353
|
+
this.guarantor = new SubscriptionGuarantor(this);
|
354
|
+
this.subscriptions = [];
|
355
|
+
}
|
356
|
+
create(channelName, mixin) {
|
357
|
+
const channel = channelName;
|
358
|
+
const params = typeof channel === "object" ? channel : {
|
359
|
+
channel: channel
|
360
|
+
};
|
361
|
+
const subscription = new Subscription(this.consumer, params, mixin);
|
362
|
+
return this.add(subscription);
|
363
|
+
}
|
364
|
+
add(subscription) {
|
365
|
+
this.subscriptions.push(subscription);
|
366
|
+
this.consumer.ensureActiveConnection();
|
367
|
+
this.notify(subscription, "initialized");
|
368
|
+
this.subscribe(subscription);
|
369
|
+
return subscription;
|
370
|
+
}
|
371
|
+
remove(subscription) {
|
372
|
+
this.forget(subscription);
|
373
|
+
if (!this.findAll(subscription.identifier).length) {
|
374
|
+
this.sendCommand(subscription, "unsubscribe");
|
375
|
+
}
|
376
|
+
return subscription;
|
377
|
+
}
|
378
|
+
reject(identifier) {
|
379
|
+
return this.findAll(identifier).map((subscription => {
|
380
|
+
this.forget(subscription);
|
381
|
+
this.notify(subscription, "rejected");
|
382
|
+
return subscription;
|
383
|
+
}));
|
384
|
+
}
|
385
|
+
forget(subscription) {
|
386
|
+
this.guarantor.forget(subscription);
|
387
|
+
this.subscriptions = this.subscriptions.filter((s => s !== subscription));
|
388
|
+
return subscription;
|
389
|
+
}
|
390
|
+
findAll(identifier) {
|
391
|
+
return this.subscriptions.filter((s => s.identifier === identifier));
|
392
|
+
}
|
393
|
+
reload() {
|
394
|
+
return this.subscriptions.map((subscription => this.subscribe(subscription)));
|
395
|
+
}
|
396
|
+
notifyAll(callbackName, ...args) {
|
397
|
+
return this.subscriptions.map((subscription => this.notify(subscription, callbackName, ...args)));
|
398
|
+
}
|
399
|
+
notify(subscription, callbackName, ...args) {
|
400
|
+
let subscriptions;
|
401
|
+
if (typeof subscription === "string") {
|
402
|
+
subscriptions = this.findAll(subscription);
|
403
|
+
} else {
|
404
|
+
subscriptions = [ subscription ];
|
405
|
+
}
|
406
|
+
return subscriptions.map((subscription => typeof subscription[callbackName] === "function" ? subscription[callbackName](...args) : undefined));
|
407
|
+
}
|
408
|
+
subscribe(subscription) {
|
409
|
+
if (this.sendCommand(subscription, "subscribe")) {
|
410
|
+
this.guarantor.guarantee(subscription);
|
411
|
+
}
|
412
|
+
}
|
413
|
+
confirmSubscription(identifier) {
|
414
|
+
logger.log(`Subscription confirmed ${identifier}`);
|
415
|
+
this.findAll(identifier).map((subscription => this.guarantor.forget(subscription)));
|
416
|
+
}
|
417
|
+
sendCommand(subscription, command) {
|
418
|
+
const {identifier: identifier} = subscription;
|
419
|
+
return this.consumer.send({
|
420
|
+
command: command,
|
421
|
+
identifier: identifier
|
422
|
+
});
|
423
|
+
}
|
424
|
+
}
|
425
|
+
class Consumer {
|
426
|
+
constructor(url) {
|
427
|
+
this._url = url;
|
428
|
+
this.subscriptions = new Subscriptions(this);
|
429
|
+
this.connection = new Connection(this);
|
430
|
+
}
|
431
|
+
get url() {
|
432
|
+
return createWebSocketURL(this._url);
|
433
|
+
}
|
434
|
+
send(data) {
|
435
|
+
return this.connection.send(data);
|
436
|
+
}
|
437
|
+
connect() {
|
438
|
+
return this.connection.open();
|
439
|
+
}
|
440
|
+
disconnect() {
|
441
|
+
return this.connection.close({
|
442
|
+
allowReconnect: false
|
443
|
+
});
|
444
|
+
}
|
445
|
+
ensureActiveConnection() {
|
446
|
+
if (!this.connection.isActive()) {
|
447
|
+
return this.connection.open();
|
448
|
+
}
|
449
|
+
}
|
450
|
+
}
|
451
|
+
function createWebSocketURL(url) {
|
452
|
+
if (typeof url === "function") {
|
453
|
+
url = url();
|
454
|
+
}
|
455
|
+
if (url && !/^wss?:/i.test(url)) {
|
456
|
+
const a = document.createElement("a");
|
457
|
+
a.href = url;
|
458
|
+
a.href = a.href;
|
459
|
+
a.protocol = a.protocol.replace("http", "ws");
|
460
|
+
return a.href;
|
461
|
+
} else {
|
462
|
+
return url;
|
463
|
+
}
|
464
|
+
}
|
465
|
+
function createConsumer(url = getConfig("url") || INTERNAL.default_mount_path) {
|
466
|
+
return new Consumer(url);
|
467
|
+
}
|
468
|
+
function getConfig(name) {
|
469
|
+
const element = document.head.querySelector(`meta[name='action-cable-${name}']`);
|
470
|
+
if (element) {
|
471
|
+
return element.getAttribute("content");
|
472
|
+
}
|
473
|
+
}
|
474
|
+
exports.Connection = Connection;
|
475
|
+
exports.ConnectionMonitor = ConnectionMonitor;
|
476
|
+
exports.Consumer = Consumer;
|
477
|
+
exports.INTERNAL = INTERNAL;
|
478
|
+
exports.Subscription = Subscription;
|
479
|
+
exports.SubscriptionGuarantor = SubscriptionGuarantor;
|
480
|
+
exports.Subscriptions = Subscriptions;
|
481
|
+
exports.adapters = adapters;
|
482
|
+
exports.createConsumer = createConsumer;
|
483
|
+
exports.createWebSocketURL = createWebSocketURL;
|
484
|
+
exports.getConfig = getConfig;
|
485
|
+
exports.logger = logger;
|
486
|
+
Object.defineProperty(exports, "__esModule", {
|
487
|
+
value: true
|
488
|
+
});
|
489
|
+
}));
|