diff --git a/public/admin.css b/public/admin.css
index 1dae6e1..91dc80b 100644
--- a/public/admin.css
+++ b/public/admin.css
@@ -231,10 +231,8 @@ label { display: grid; gap: 6px; color: var(--muted); font-size: 13px; }
width: auto;
margin: 0;
}
-.launcher-preview-settings {
- grid-template-columns: 1fr;
-}
.launcher-preview-stage {
+ grid-column: 1 / -1;
min-height: 112px;
display: grid;
place-items: center;
@@ -274,6 +272,52 @@ label { display: grid; gap: 6px; color: var(--muted); font-size: 13px; }
content: "";
animation: launcherPreviewRing 2.2s ease-out infinite;
}
+.launcher-preview.notify-pulse::after {
+ position: absolute;
+ inset: 0;
+ border-radius: 50%;
+ pointer-events: none;
+ content: "";
+ animation: launcherPreviewPulse 1.15s ease-out infinite;
+}
+.launcher-preview.notify-wiggle .launcher-preview-icon {
+ animation: launcherPreviewWiggle .62s ease-in-out infinite;
+}
+.launcher-preview-status {
+ position: absolute;
+ top: -3px;
+ left: -3px;
+ width: 14px;
+ height: 14px;
+ border: 2px solid #ffffff;
+ border-radius: 50%;
+ background: #c9d4ce;
+ box-shadow: 0 0 0 4px rgb(201 212 206 / 24%);
+}
+.launcher-preview.online .launcher-preview-status {
+ background: #2f9e44;
+ box-shadow: 0 0 0 4px rgb(47 158 68 / 16%);
+}
+.launcher-preview-badge {
+ position: absolute;
+ top: -5px;
+ right: -5px;
+ min-width: 22px;
+ height: 22px;
+ display: none;
+ place-items: center;
+ border: 2px solid #ffffff;
+ border-radius: 999px;
+ background: #ff3b30;
+ color: #ffffff;
+ font-size: 12px;
+ font-weight: 800;
+ line-height: 1;
+ box-shadow: 0 8px 18px rgb(0 0 0 / 18%);
+}
+.launcher-preview.show-badge .launcher-preview-badge {
+ display: grid;
+}
.launcher-preview-label {
position: absolute;
right: 68px;
@@ -415,6 +459,17 @@ label { display: grid; gap: 6px; color: var(--muted); font-size: 13px; }
70% { transform: scale(1.22); opacity: 0; }
100% { transform: scale(.92); opacity: 0; }
}
+@keyframes launcherPreviewPulse {
+ 0% { box-shadow: 0 0 0 0 rgb(255 59 48 / 46%); opacity: .9; transform: scale(1); }
+ 70% { box-shadow: 0 0 0 18px rgb(255 59 48 / 0%); opacity: 0; transform: scale(1.08); }
+ 100% { box-shadow: 0 0 0 0 rgb(255 59 48 / 0%); opacity: 0; transform: scale(1); }
+}
+@keyframes launcherPreviewWiggle {
+ 0%, 100% { transform: translateY(0) rotate(0deg); }
+ 22% { transform: translateY(-3px) rotate(-4deg); }
+ 48% { transform: translateY(2px) rotate(3deg); }
+ 72% { transform: translateY(-1px) rotate(-2deg); }
+}
.widget-language-settings {
grid-template-columns: 112px minmax(230px, 1fr);
}
diff --git a/public/admin.html b/public/admin.html
index c03e9a6..064b1f1 100644
--- a/public/admin.html
+++ b/public/admin.html
@@ -173,13 +173,12 @@
-
-
@@ -189,6 +188,13 @@
+
+
+
+ Nova odpoved
+ 1
+
+
Ulozit widget
diff --git a/public/admin.js b/public/admin.js
index f723ea2..6f13e48 100644
--- a/public/admin.js
+++ b/public/admin.js
@@ -143,12 +143,12 @@ $("#settingsForm").defaultLanguage.addEventListener("change", () => {
renderLauncherPreview();
});
$("#settingsForm").addEventListener("input", (event) => {
- if (event.target.matches("[name='launcherShape'], [name='launcherBreathe'], [name='launcherRing'], [name='launcherHoverLabel'], [name='copyOnlineLabel']")) {
+ if (event.target.matches("[name='launcherShape'], [name='launcherBreathe'], [name='launcherRing'], [name='launcherHoverLabel'], [name='copyOnlineLabel'], [name='messagePulse'], [name='messageBadge'], [name='messageLabel'], [name='messageWiggle'], [name='copyNewReplyLabel']")) {
renderLauncherPreview();
}
});
$("#settingsForm").addEventListener("change", (event) => {
- if (event.target.matches("[name='launcherShape'], [name='launcherBreathe'], [name='launcherRing'], [name='launcherHoverLabel']")) {
+ if (event.target.matches("[name='launcherShape'], [name='launcherBreathe'], [name='launcherRing'], [name='launcherHoverLabel'], [name='messagePulse'], [name='messageBadge'], [name='messageLabel'], [name='messageWiggle']")) {
renderLauncherPreview();
}
});
@@ -641,22 +641,37 @@ function renderWidgetCopyFields(language) {
function renderLauncherPreview() {
const preview = $("#launcherPreview");
+ const messagePreview = $("#messageEffectPreview");
const form = $("#settingsForm");
- if (!preview || !form) return;
+ if (!preview || !messagePreview || !form) return;
const shape = ["circle", "bubble", "messenger", "whatsapp"].includes(form.launcherShape.value)
? form.launcherShape.value
: "bubble";
const brand = normalizeHexColor(form.brandHex.value) || normalizeHexColor(form.brand.value) || "#0f8f6f";
- preview.style.setProperty("--preview-brand", brand);
- preview.className = [
+ const baseClasses = [
"launcher-preview",
- `preview-shape-${shape}`,
+ `preview-shape-${shape}`
+ ];
+ preview.style.setProperty("--preview-brand", brand);
+ messagePreview.style.setProperty("--preview-brand", brand);
+ preview.className = [
+ ...baseClasses,
+ $("#onlineToggle").checked ? "online" : "",
form.launcherBreathe.checked ? "effect-breathe" : "",
form.launcherRing.checked ? "effect-ring" : "",
form.launcherHoverLabel.checked ? "show-label" : ""
].filter(Boolean).join(" ");
+ messagePreview.className = [
+ ...baseClasses,
+ form.messagePulse.checked ? "notify-pulse" : "",
+ form.messageBadge.checked ? "show-badge" : "",
+ form.messageLabel.checked ? "show-label" : "",
+ form.messageWiggle.checked ? "notify-wiggle" : ""
+ ].filter(Boolean).join(" ");
const label = preview.querySelector(".launcher-preview-label");
if (label) label.textContent = form.copyOnlineLabel.value || "Napiste nam";
+ const messageLabel = messagePreview.querySelector(".launcher-preview-label");
+ if (messageLabel) messageLabel.textContent = form.copyNewReplyLabel.value || "Nova odpoved";
}
function widgetCopyForAdmin(settings, language) {