livechat 0.1.0 → 0.2.1
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/CHANGELOG.md +13 -0
- data/README.md +8 -2
- data/lib/livechat/version.rb +1 -1
- data/lib/livechat/widget.js +67 -22
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ab3b69e1c61320ea9df88571fc2fcad40c09c44e0f14f961b59a87d23ffc161e
|
|
4
|
+
data.tar.gz: b6750a5aef1f99e7a6d2a49ed2fbcd6bb9cb1fb992cefd176e552f7d281f42e8
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 12421cafc2a629e4d1621dea03a984bd1e88d6ae9418390bd9767533208827da379f3d858cfd1c1eb1a6b47d2bb1aebaecedce8ff810f7f4fdc1197473c276e3
|
|
7
|
+
data.tar.gz: 53b24b739628a3fdf69082ff652a1770d1acfa18c385152e61a2f9985faa82eac968f0c0be4ff36561957d9d8a3fa2bd53c7c671d2df02d0564ac10a96bc8eda
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.2.1
|
|
4
|
+
|
|
5
|
+
- With `show_launcher = false` the panel now sits in the corner instead of
|
|
6
|
+
hovering 66px above a launcher bubble that isn't there.
|
|
7
|
+
|
|
8
|
+
## 0.2.0
|
|
9
|
+
|
|
10
|
+
- Unread count badges on `data-livechat-open` elements, so launcher-less
|
|
11
|
+
setups (`show_launcher = false`) still surface waiting replies.
|
|
12
|
+
- Message prefill: `data-livechat-message="…"` on any opener, or
|
|
13
|
+
`window.Livechat.open("…")` — seeds the message box for contextual asks,
|
|
14
|
+
never overwriting a visitor's draft.
|
|
15
|
+
|
|
3
16
|
## 0.1.0
|
|
4
17
|
|
|
5
18
|
- Initial release: floating chat widget (guests + signed-in visitors, one
|
data/README.md
CHANGED
|
@@ -134,8 +134,14 @@ reply. Gated by `config.authorize_agent` (development-only until you set it).
|
|
|
134
134
|
|
|
135
135
|
## Widget API
|
|
136
136
|
|
|
137
|
-
- `window.Livechat.open()` / `window.Livechat.close()`
|
|
138
|
-
|
|
137
|
+
- `window.Livechat.open()` / `window.Livechat.close()` —
|
|
138
|
+
`open("Hi, I need help with…")` prefills the message box (never over a
|
|
139
|
+
visitor's draft)
|
|
140
|
+
- Any element with `data-livechat-open` opens the panel on click; add
|
|
141
|
+
`data-livechat-message="…"` to prefill — great for contextual buttons
|
|
142
|
+
("Request verification", "Ask about billing")
|
|
143
|
+
- While replies are unread, every `data-livechat-open` element carries a
|
|
144
|
+
small count badge — so hiding the launcher doesn't hide the answer
|
|
139
145
|
- `<%= livechat_button %>` renders a plain, unstyled opener button
|
|
140
146
|
- `config.show_launcher = false` hides the bubble entirely — bring your own
|
|
141
147
|
entry point
|
data/lib/livechat/version.rb
CHANGED
data/lib/livechat/widget.js
CHANGED
|
@@ -83,6 +83,7 @@
|
|
|
83
83
|
injectStyles();
|
|
84
84
|
mount();
|
|
85
85
|
applyBrandColor();
|
|
86
|
+
syncOpenerBadges(); // a Turbo visit brings fresh openers — restamp them
|
|
86
87
|
|
|
87
88
|
if (sessionGet("livechat_open") === "1") {
|
|
88
89
|
openPanel();
|
|
@@ -100,7 +101,7 @@
|
|
|
100
101
|
if (!opener) return;
|
|
101
102
|
event.preventDefault();
|
|
102
103
|
event.stopPropagation();
|
|
103
|
-
openPanel();
|
|
104
|
+
openPanel(opener.getAttribute("data-livechat-message"));
|
|
104
105
|
}
|
|
105
106
|
|
|
106
107
|
// --- mounting ---------------------------------------------------------------
|
|
@@ -115,6 +116,9 @@
|
|
|
115
116
|
root = document.createElement("div");
|
|
116
117
|
root.id = "lvc-root";
|
|
117
118
|
if (config.rtl) root.setAttribute("dir", "rtl");
|
|
119
|
+
// No launcher bubble to clear — the panel sits in the corner instead of
|
|
120
|
+
// hovering 66px above nothing.
|
|
121
|
+
if (!config.launcher) root.className = "lvc-no-launcher";
|
|
118
122
|
|
|
119
123
|
if (config.launcher) root.appendChild(buildLauncher());
|
|
120
124
|
document.body.appendChild(root);
|
|
@@ -287,24 +291,33 @@
|
|
|
287
291
|
|
|
288
292
|
// --- open / close -----------------------------------------------------------
|
|
289
293
|
|
|
290
|
-
|
|
294
|
+
// prefill (optional string, from data-livechat-message or
|
|
295
|
+
// Livechat.open("…")) seeds the input — but never over a visitor's draft.
|
|
296
|
+
function openPanel(prefill) {
|
|
291
297
|
mount();
|
|
292
|
-
if (isOpen)
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
298
|
+
if (!isOpen) {
|
|
299
|
+
isOpen = true;
|
|
300
|
+
sessionSet("livechat_open", "1");
|
|
301
|
+
|
|
302
|
+
// The panel is built once and then hidden/shown — closing must never
|
|
303
|
+
// throw away the rendered thread or a half-written message.
|
|
304
|
+
var panel = document.getElementById("lvc-panel");
|
|
305
|
+
if (!panel) {
|
|
306
|
+
panel = buildPanel();
|
|
307
|
+
root.appendChild(panel);
|
|
308
|
+
}
|
|
309
|
+
panel.hidden = false;
|
|
310
|
+
setUnread(0);
|
|
311
|
+
poll();
|
|
312
|
+
schedulePoll();
|
|
313
|
+
}
|
|
314
|
+
if (inputEl) {
|
|
315
|
+
if (typeof prefill === "string" && prefill && !inputEl.value.trim()) {
|
|
316
|
+
inputEl.value = prefill;
|
|
317
|
+
autogrow();
|
|
318
|
+
}
|
|
319
|
+
inputEl.focus();
|
|
302
320
|
}
|
|
303
|
-
panel.hidden = false;
|
|
304
|
-
setUnread(0);
|
|
305
|
-
poll();
|
|
306
|
-
schedulePoll();
|
|
307
|
-
if (inputEl) inputEl.focus();
|
|
308
321
|
}
|
|
309
322
|
|
|
310
323
|
function closePanel() {
|
|
@@ -356,10 +369,35 @@
|
|
|
356
369
|
.catch(function () { fetching = false; });
|
|
357
370
|
}
|
|
358
371
|
|
|
372
|
+
var unreadCount = 0;
|
|
373
|
+
|
|
359
374
|
function setUnread(count) {
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
375
|
+
unreadCount = count;
|
|
376
|
+
if (badgeEl) {
|
|
377
|
+
badgeEl.hidden = !(count > 0);
|
|
378
|
+
badgeEl.textContent = count > 9 ? "9+" : String(count);
|
|
379
|
+
}
|
|
380
|
+
syncOpenerBadges();
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
// Hosts that hide the launcher still get an unread indicator: every
|
|
384
|
+
// data-livechat-open element carries a small count badge while replies
|
|
385
|
+
// are waiting, and loses it the moment the panel opens.
|
|
386
|
+
function syncOpenerBadges() {
|
|
387
|
+
var openers = document.querySelectorAll("[data-livechat-open]");
|
|
388
|
+
for (var i = 0; i < openers.length; i++) {
|
|
389
|
+
var badge = openers[i].querySelector(".lvc-opener-badge");
|
|
390
|
+
if (unreadCount > 0) {
|
|
391
|
+
if (!badge) {
|
|
392
|
+
badge = document.createElement("span");
|
|
393
|
+
badge.className = "lvc-opener-badge";
|
|
394
|
+
openers[i].appendChild(badge);
|
|
395
|
+
}
|
|
396
|
+
badge.textContent = unreadCount > 9 ? "9+" : String(unreadCount);
|
|
397
|
+
} else if (badge) {
|
|
398
|
+
badge.remove();
|
|
399
|
+
}
|
|
400
|
+
}
|
|
363
401
|
}
|
|
364
402
|
|
|
365
403
|
function syncEmailRow() {
|
|
@@ -509,7 +547,9 @@
|
|
|
509
547
|
"border-radius:14px;box-shadow:0 12px 40px rgba(0,0,0,.28);display:flex;flex-direction:column;overflow:hidden}" +
|
|
510
548
|
"#lvc-panel[hidden]{display:none}" +
|
|
511
549
|
"#lvc-root[dir=rtl] #lvc-panel{right:auto;left:20px}" +
|
|
512
|
-
"
|
|
550
|
+
"#lvc-root.lvc-no-launcher #lvc-panel{bottom:20px;max-height:calc(100dvh - 40px)}" +
|
|
551
|
+
"@media(max-width:480px){#lvc-panel{right:12px;bottom:80px}" +
|
|
552
|
+
"#lvc-root.lvc-no-launcher #lvc-panel{right:12px;bottom:12px;max-height:calc(100dvh - 24px)}}" +
|
|
513
553
|
"#lvc-header{display:flex;align-items:flex-start;justify-content:space-between;gap:8px;" +
|
|
514
554
|
"padding:14px 16px;background:var(--lvc-accent);color:var(--lvc-accent-text)}" +
|
|
515
555
|
"#lvc-header strong{display:block;font-size:15px}" +
|
|
@@ -553,7 +593,12 @@
|
|
|
553
593
|
"color:var(--lvc-accent-text);width:40px;min-width:40px;height:40px;align-self:flex-end;" +
|
|
554
594
|
"display:flex;align-items:center;justify-content:center;cursor:pointer}" +
|
|
555
595
|
"#lvc-form button:disabled{opacity:.6;cursor:default}" +
|
|
556
|
-
"#lvc-root[dir=rtl] #lvc-form button svg{transform:scaleX(-1)}"
|
|
596
|
+
"#lvc-root[dir=rtl] #lvc-form button svg{transform:scaleX(-1)}" +
|
|
597
|
+
// Lives in host DOM (on data-livechat-open elements), so no #lvc-root prefix.
|
|
598
|
+
".lvc-opener-badge{display:inline-flex;min-width:18px;height:18px;padding:0 5px;" +
|
|
599
|
+
"margin-inline-start:6px;border-radius:999px;background:#dc2626;color:#fff;" +
|
|
600
|
+
"font-size:11px;font-weight:700;line-height:18px;align-items:center;" +
|
|
601
|
+
"justify-content:center;vertical-align:middle}";
|
|
557
602
|
|
|
558
603
|
var style = document.createElement("style");
|
|
559
604
|
style.id = "lvc-styles";
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: livechat
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1
|
|
4
|
+
version: 0.2.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Yaroslav Shmarov
|
|
@@ -118,7 +118,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
118
118
|
- !ruby/object:Gem::Version
|
|
119
119
|
version: '0'
|
|
120
120
|
requirements: []
|
|
121
|
-
rubygems_version:
|
|
121
|
+
rubygems_version: 3.6.9
|
|
122
122
|
specification_version: 4
|
|
123
123
|
summary: 'Open-source live chat for Rails: a drop-in support widget plus a team inbox,
|
|
124
124
|
in your own database.'
|