Add configurable new message effects
This commit is contained in:
+7
-5
@@ -115,13 +115,15 @@
|
|||||||
<label><input name="launcherBreathe" type="checkbox"> jemne dychani</label>
|
<label><input name="launcherBreathe" type="checkbox"> jemne dychani</label>
|
||||||
<label><input name="launcherRing" type="checkbox"> svetelny prstenec</label>
|
<label><input name="launcherRing" type="checkbox"> svetelny prstenec</label>
|
||||||
<label><input name="launcherHoverLabel" type="checkbox"> napis pri najeti</label>
|
<label><input name="launcherHoverLabel" type="checkbox"> napis pri najeti</label>
|
||||||
<label><input name="launcherWave" type="checkbox"> jednorazova vlna</label>
|
|
||||||
<label><input name="launcherAvatar" type="checkbox"> mini avatar styl</label>
|
<label><input name="launcherAvatar" type="checkbox"> mini avatar styl</label>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
<label class="switch setting-switch">
|
<fieldset class="effect-settings">
|
||||||
<input name="pulseOnAdminReply" type="checkbox">
|
<legend>Efekt pri nove zprave</legend>
|
||||||
<span>Pulzovani widgetu pri odpovedi</span>
|
<label><input name="messagePulse" type="checkbox"> pulzovani</label>
|
||||||
</label>
|
<label><input name="messageBadge" type="checkbox"> badge s poctem</label>
|
||||||
|
<label><input name="messageLabel" type="checkbox"> kratky stitek</label>
|
||||||
|
<label><input name="messageWiggle" type="checkbox"> zhoupnuti</label>
|
||||||
|
</fieldset>
|
||||||
<button type="submit">Ulozit</button>
|
<button type="submit">Ulozit</button>
|
||||||
</form>
|
</form>
|
||||||
<h3>GTM snippet</h3>
|
<h3>GTM snippet</h3>
|
||||||
|
|||||||
+8
-4
@@ -83,11 +83,13 @@ $("#settingsForm").addEventListener("submit", async (event) => {
|
|||||||
breathe: form.get("launcherBreathe") === "on",
|
breathe: form.get("launcherBreathe") === "on",
|
||||||
ring: form.get("launcherRing") === "on",
|
ring: form.get("launcherRing") === "on",
|
||||||
hoverLabel: form.get("launcherHoverLabel") === "on",
|
hoverLabel: form.get("launcherHoverLabel") === "on",
|
||||||
wave: form.get("launcherWave") === "on",
|
|
||||||
avatar: form.get("launcherAvatar") === "on"
|
avatar: form.get("launcherAvatar") === "on"
|
||||||
};
|
};
|
||||||
settings.notifications = settings.notifications || {};
|
settings.notifications = settings.notifications || {};
|
||||||
settings.notifications.pulseOnAdminReply = form.get("pulseOnAdminReply") === "on";
|
settings.notifications.pulseOnAdminReply = form.get("messagePulse") === "on";
|
||||||
|
settings.notifications.badgeOnAdminReply = form.get("messageBadge") === "on";
|
||||||
|
settings.notifications.labelOnAdminReply = form.get("messageLabel") === "on";
|
||||||
|
settings.notifications.wiggleOnAdminReply = form.get("messageWiggle") === "on";
|
||||||
await saveSite({ settings, isOnline: state.site.isOnline });
|
await saveSite({ settings, isOnline: state.site.isOnline });
|
||||||
$("#settingsPanel").classList.add("hidden");
|
$("#settingsPanel").classList.add("hidden");
|
||||||
});
|
});
|
||||||
@@ -334,9 +336,11 @@ function renderSite() {
|
|||||||
form.launcherBreathe.checked = s.launcherEffects?.breathe !== false;
|
form.launcherBreathe.checked = s.launcherEffects?.breathe !== false;
|
||||||
form.launcherRing.checked = s.launcherEffects?.ring !== false;
|
form.launcherRing.checked = s.launcherEffects?.ring !== false;
|
||||||
form.launcherHoverLabel.checked = s.launcherEffects?.hoverLabel !== false;
|
form.launcherHoverLabel.checked = s.launcherEffects?.hoverLabel !== false;
|
||||||
form.launcherWave.checked = s.launcherEffects?.wave !== false;
|
|
||||||
form.launcherAvatar.checked = s.launcherEffects?.avatar !== false;
|
form.launcherAvatar.checked = s.launcherEffects?.avatar !== false;
|
||||||
form.pulseOnAdminReply.checked = s.notifications?.pulseOnAdminReply !== false;
|
form.messagePulse.checked = s.notifications?.pulseOnAdminReply !== false;
|
||||||
|
form.messageBadge.checked = s.notifications?.badgeOnAdminReply !== false;
|
||||||
|
form.messageLabel.checked = s.notifications?.labelOnAdminReply !== false;
|
||||||
|
form.messageWiggle.checked = s.notifications?.wiggleOnAdminReply !== false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderConversations() {
|
function renderConversations() {
|
||||||
|
|||||||
+49
-7
@@ -28,6 +28,8 @@
|
|||||||
<button class="mf-launcher ${launcherEffectClasses(settings, site.isOnline)}" type="button" aria-label="${copy.title}">
|
<button class="mf-launcher ${launcherEffectClasses(settings, site.isOnline)}" type="button" aria-label="${copy.title}">
|
||||||
<span class="mf-launcher-icon"></span>
|
<span class="mf-launcher-icon"></span>
|
||||||
<span class="mf-launcher-label">${escapeHtml(site.isOnline ? "Jsme online" : "Offline")}</span>
|
<span class="mf-launcher-label">${escapeHtml(site.isOnline ? "Jsme online" : "Offline")}</span>
|
||||||
|
<span class="mf-message-badge" hidden>0</span>
|
||||||
|
<span class="mf-message-label">Nova odpoved</span>
|
||||||
</button>
|
</button>
|
||||||
<section class="mf-panel" aria-live="polite">
|
<section class="mf-panel" aria-live="polite">
|
||||||
<header>
|
<header>
|
||||||
@@ -70,12 +72,16 @@
|
|||||||
const dropzone = root.querySelector(".mf-dropzone");
|
const dropzone = root.querySelector(".mf-dropzone");
|
||||||
const attachmentList = root.querySelector(".mf-attachment-list");
|
const attachmentList = root.querySelector(".mf-attachment-list");
|
||||||
let selectedFiles = [];
|
let selectedFiles = [];
|
||||||
|
let unreadAdminCount = 0;
|
||||||
renderSoundState(soundButton);
|
renderSoundState(soundButton);
|
||||||
|
|
||||||
launcher.addEventListener("click", () => {
|
launcher.addEventListener("click", () => {
|
||||||
panel.classList.toggle("open");
|
panel.classList.toggle("open");
|
||||||
if (panel.classList.contains("open")) {
|
if (panel.classList.contains("open")) {
|
||||||
launcher.classList.remove("mf-notify");
|
launcher.classList.remove("mf-notify");
|
||||||
|
clearMessageEffects(launcher);
|
||||||
|
unreadAdminCount = 0;
|
||||||
|
updateMessageBadge(launcher, unreadAdminCount);
|
||||||
scrollMessagesToBottom(messages);
|
scrollMessagesToBottom(messages);
|
||||||
markConversationSeen();
|
markConversationSeen();
|
||||||
}
|
}
|
||||||
@@ -204,8 +210,9 @@
|
|||||||
if (panel.classList.contains("open")) markConversationSeen();
|
if (panel.classList.contains("open")) markConversationSeen();
|
||||||
const eventMessages = data.payload?.messages || [];
|
const eventMessages = data.payload?.messages || [];
|
||||||
const lastMessage = eventMessages[eventMessages.length - 1];
|
const lastMessage = eventMessages[eventMessages.length - 1];
|
||||||
if (settings.notifications?.pulseOnAdminReply !== false && lastMessage?.senderType === "admin" && !panel.classList.contains("open")) {
|
if (lastMessage?.senderType === "admin" && !panel.classList.contains("open")) {
|
||||||
launcher.classList.add("mf-notify");
|
unreadAdminCount += 1;
|
||||||
|
applyAdminReplyEffects(launcher, settings, unreadAdminCount);
|
||||||
playNotifySound();
|
playNotifySound();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -421,11 +428,41 @@
|
|||||||
effects.breathe ? "mf-effect-breathe" : "",
|
effects.breathe ? "mf-effect-breathe" : "",
|
||||||
effects.ring ? "mf-effect-ring" : "",
|
effects.ring ? "mf-effect-ring" : "",
|
||||||
effects.hoverLabel ? "mf-effect-hover-label" : "",
|
effects.hoverLabel ? "mf-effect-hover-label" : "",
|
||||||
effects.wave ? "mf-effect-wave" : "",
|
|
||||||
effects.avatar ? "mf-effect-avatar" : ""
|
effects.avatar ? "mf-effect-avatar" : ""
|
||||||
].filter(Boolean).join(" ");
|
].filter(Boolean).join(" ");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function applyAdminReplyEffects(launcher, settings, unreadCount) {
|
||||||
|
const notifications = settings.notifications || {};
|
||||||
|
if (notifications.pulseOnAdminReply !== false) launcher.classList.add("mf-notify");
|
||||||
|
if (notifications.badgeOnAdminReply !== false) updateMessageBadge(launcher, unreadCount);
|
||||||
|
if (notifications.labelOnAdminReply !== false) {
|
||||||
|
launcher.classList.add("mf-show-message-label");
|
||||||
|
clearTimeout(applyAdminReplyEffects.labelTimer);
|
||||||
|
applyAdminReplyEffects.labelTimer = setTimeout(() => launcher.classList.remove("mf-show-message-label"), 4200);
|
||||||
|
}
|
||||||
|
if (notifications.wiggleOnAdminReply !== false) {
|
||||||
|
launcher.classList.remove("mf-wiggle");
|
||||||
|
void launcher.offsetWidth;
|
||||||
|
launcher.classList.add("mf-wiggle");
|
||||||
|
clearTimeout(applyAdminReplyEffects.wiggleTimer);
|
||||||
|
applyAdminReplyEffects.wiggleTimer = setTimeout(() => launcher.classList.remove("mf-wiggle"), 1400);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearMessageEffects(launcher) {
|
||||||
|
launcher.classList.remove("mf-notify", "mf-wiggle", "mf-show-message-label");
|
||||||
|
clearTimeout(applyAdminReplyEffects.labelTimer);
|
||||||
|
clearTimeout(applyAdminReplyEffects.wiggleTimer);
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateMessageBadge(launcher, unreadCount) {
|
||||||
|
const badge = launcher.querySelector(".mf-message-badge");
|
||||||
|
if (!badge) return;
|
||||||
|
badge.hidden = unreadCount <= 0;
|
||||||
|
badge.textContent = unreadCount > 9 ? "9+" : String(unreadCount);
|
||||||
|
}
|
||||||
|
|
||||||
function styles(settings) {
|
function styles(settings) {
|
||||||
const c = settings.colors;
|
const c = settings.colors;
|
||||||
const desktop = settings.desktop;
|
const desktop = settings.desktop;
|
||||||
@@ -446,14 +483,17 @@
|
|||||||
.mf-launcher-icon:after { transform: translateY(5px); width: 18px; }
|
.mf-launcher-icon:after { transform: translateY(5px); width: 18px; }
|
||||||
.mf-launcher-label { position: absolute; ${labelOffset} top: 50%; transform: translateY(-50%) translateX(8px); opacity: 0; pointer-events: none; white-space: nowrap; border-radius: 999px; padding: 7px 10px; background: ${c.text}; color: white; font-size: 12px; box-shadow: 0 10px 24px rgb(0 0 0 / 18%); transition: opacity .18s ease, transform .18s ease; }
|
.mf-launcher-label { position: absolute; ${labelOffset} top: 50%; transform: translateY(-50%) translateX(8px); opacity: 0; pointer-events: none; white-space: nowrap; border-radius: 999px; padding: 7px 10px; background: ${c.text}; color: white; font-size: 12px; box-shadow: 0 10px 24px rgb(0 0 0 / 18%); transition: opacity .18s ease, transform .18s ease; }
|
||||||
.mf-effect-hover-label:hover .mf-launcher-label { opacity: 1; transform: translateY(-50%) translateX(0); }
|
.mf-effect-hover-label:hover .mf-launcher-label { opacity: 1; transform: translateY(-50%) translateX(0); }
|
||||||
|
.mf-message-label { position: absolute; ${labelOffset} top: 50%; transform: translateY(-50%) translateX(8px); opacity: 0; pointer-events: none; white-space: nowrap; border-radius: 999px; padding: 7px 10px; background: ${c.text}; color: white; font-size: 12px; font-weight: 700; box-shadow: 0 10px 24px rgb(0 0 0 / 18%); transition: opacity .18s ease, transform .18s ease; }
|
||||||
|
.mf-show-message-label .mf-message-label { opacity: 1; transform: translateY(-50%) translateX(0); }
|
||||||
|
.mf-message-badge { position: absolute; top: -5px; right: -5px; min-width: 22px; height: 22px; display: grid; place-items: center; border-radius: 999px; border: 2px solid white; background: #ff3b30; color: white; font-size: 12px; font-weight: 800; line-height: 1; box-shadow: 0 8px 18px rgb(0 0 0 / 18%); }
|
||||||
.mf-online.mf-effect-breathe { animation: mfBreathe 2.8s ease-in-out infinite; }
|
.mf-online.mf-effect-breathe { animation: mfBreathe 2.8s ease-in-out infinite; }
|
||||||
.mf-online.mf-effect-ring:before { position: absolute; inset: -5px; border: 2px solid ${c.brand}; border-radius: 50%; opacity: .62; content: ""; animation: mfRing 2.2s ease-out infinite; }
|
.mf-online.mf-effect-ring:before { position: absolute; inset: -5px; border: 2px solid ${c.brand}; border-radius: 50%; opacity: .62; content: ""; animation: mfRing 2.2s ease-out infinite; }
|
||||||
.mf-online.mf-effect-wave:after { position: absolute; inset: 0; border-radius: 50%; content: ""; box-shadow: 0 0 0 0 rgb(15 143 111 / 42%); animation: mfWaveOnce 1.7s ease-out 1 .6s; pointer-events: none; }
|
|
||||||
.mf-effect-avatar .mf-launcher-icon { width: 26px; height: 20px; border-radius: 12px 12px 10px 10px; background: rgb(255 255 255 / 24%); border: 2px solid ${c.brandText}; position: relative; }
|
.mf-effect-avatar .mf-launcher-icon { width: 26px; height: 20px; border-radius: 12px 12px 10px 10px; background: rgb(255 255 255 / 24%); border: 2px solid ${c.brandText}; position: relative; }
|
||||||
.mf-effect-avatar .mf-launcher-icon:before { position: absolute; left: 6px; top: 6px; width: 4px; height: 4px; border-radius: 50%; background: ${c.brandText}; transform: none; box-shadow: 10px 0 0 ${c.brandText}; }
|
.mf-effect-avatar .mf-launcher-icon:before { position: absolute; left: 6px; top: 6px; width: 4px; height: 4px; border-radius: 50%; background: ${c.brandText}; transform: none; box-shadow: 10px 0 0 ${c.brandText}; }
|
||||||
.mf-effect-avatar .mf-launcher-icon:after { position: absolute; left: 7px; top: 13px; width: 12px; height: 2px; border-radius: 999px; background: ${c.brandText}; transform: none; opacity: .88; }
|
.mf-effect-avatar .mf-launcher-icon:after { position: absolute; left: 7px; top: 13px; width: 12px; height: 2px; border-radius: 999px; background: ${c.brandText}; transform: none; opacity: .88; }
|
||||||
.mf-offline { filter: grayscale(.2) saturate(.72); opacity: .86; }
|
.mf-offline { filter: grayscale(.2) saturate(.72); opacity: .86; }
|
||||||
.mf-launcher.mf-notify { animation: mfPulse 1.15s ease-out infinite; }
|
.mf-launcher.mf-notify { animation: mfPulse 1.15s ease-out infinite; }
|
||||||
|
.mf-launcher.mf-wiggle { animation: mfWiggle .62s ease-in-out 2; }
|
||||||
.mf-panel {
|
.mf-panel {
|
||||||
position: fixed; z-index: 2147483001; ${desktop.side}: ${desktop.sideOffsetPx}px; bottom: ${desktop.bottomPx + 72}px;
|
position: fixed; z-index: 2147483001; ${desktop.side}: ${desktop.sideOffsetPx}px; bottom: ${desktop.bottomPx + 72}px;
|
||||||
width: min(${desktop.widthPx}px, calc(100vw - 24px)); max-height: min(680px, calc(100vh - 110px)); display: none;
|
width: min(${desktop.widthPx}px, calc(100vw - 24px)); max-height: min(680px, calc(100vh - 110px)); display: none;
|
||||||
@@ -512,9 +552,11 @@
|
|||||||
70% { transform: scale(1.22); opacity: 0; }
|
70% { transform: scale(1.22); opacity: 0; }
|
||||||
100% { transform: scale(.92); opacity: 0; }
|
100% { transform: scale(.92); opacity: 0; }
|
||||||
}
|
}
|
||||||
@keyframes mfWaveOnce {
|
@keyframes mfWiggle {
|
||||||
0% { transform: scale(1); opacity: .7; }
|
0%, 100% { transform: translateY(0) rotate(0deg); }
|
||||||
100% { transform: scale(1.58); opacity: 0; }
|
22% { transform: translateY(-3px) rotate(-4deg); }
|
||||||
|
48% { transform: translateY(2px) rotate(3deg); }
|
||||||
|
72% { transform: translateY(-1px) rotate(-2deg); }
|
||||||
}
|
}
|
||||||
@media (max-width: 640px) {
|
@media (max-width: 640px) {
|
||||||
.mf-launcher { ${mobile.side}: ${mobile.sideOffsetPx}px; bottom: ${mobile.bottomPx}px; }
|
.mf-launcher { ${mobile.side}: ${mobile.sideOffsetPx}px; bottom: ${mobile.bottomPx}px; }
|
||||||
|
|||||||
@@ -267,10 +267,14 @@ function defaultSettings() {
|
|||||||
breathe: true,
|
breathe: true,
|
||||||
ring: true,
|
ring: true,
|
||||||
hoverLabel: true,
|
hoverLabel: true,
|
||||||
wave: true,
|
|
||||||
avatar: true
|
avatar: true
|
||||||
},
|
},
|
||||||
notifications: { pulseOnAdminReply: true }
|
notifications: {
|
||||||
|
pulseOnAdminReply: true,
|
||||||
|
badgeOnAdminReply: true,
|
||||||
|
labelOnAdminReply: true,
|
||||||
|
wiggleOnAdminReply: true
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user