aumera-on-screen-widget 0.0.14 → 0.0.16
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/df-btn.js +372 -60
- package/package.json +1 -1
package/df-btn.js
CHANGED
|
@@ -1,30 +1,241 @@
|
|
|
1
|
-
|
|
2
|
-
const
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
}
|
|
1
|
+
(async function () {
|
|
2
|
+
const wrapper = document.querySelector("#df-btn");
|
|
3
|
+
|
|
4
|
+
// Helper function to get GraphQL endpoint based on environment
|
|
5
|
+
function getGraphQLUrl(env) {
|
|
6
|
+
return env === "dev"
|
|
7
|
+
? "https://admin.dev.aumera.ai/g/"
|
|
8
|
+
: "https://admin.aumera.ai/g/";
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// Helper function to get language from page
|
|
12
|
+
function getLanguage() {
|
|
13
|
+
// Check HTML lang attribute first
|
|
14
|
+
let lang = document.documentElement.lang || "";
|
|
15
|
+
|
|
16
|
+
// Fallback to browser language
|
|
17
|
+
if (!lang) {
|
|
18
|
+
lang = navigator.language || navigator.languages?.[0] || "en";
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Extract language code (e.g., "en" from "en-US")
|
|
22
|
+
lang = lang.split("-")[0].toLowerCase();
|
|
23
|
+
|
|
24
|
+
// Validate against supported languages
|
|
25
|
+
const supportedLangs = ["en", "de", "it", "fr", "es"];
|
|
26
|
+
return supportedLangs.includes(lang) ? lang : "de";
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Async function to fetch chatbot settings from GraphQL
|
|
30
|
+
async function fetchChatbotSettings(orgId, env, language) {
|
|
31
|
+
try {
|
|
32
|
+
const graphqlUrl = getGraphQLUrl(env);
|
|
33
|
+
console.log("[OSW Widget] Fetching settings from:", graphqlUrl);
|
|
34
|
+
console.log(
|
|
35
|
+
"[OSW Widget] Request params - orgId:",
|
|
36
|
+
orgId,
|
|
37
|
+
"env:",
|
|
38
|
+
env,
|
|
39
|
+
"language:",
|
|
40
|
+
language
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
const query = `
|
|
44
|
+
query osw {
|
|
45
|
+
oswChatbotSettingsPublic(organizationId: ${orgId}) {
|
|
46
|
+
message
|
|
47
|
+
success
|
|
48
|
+
settings {
|
|
49
|
+
animation
|
|
50
|
+
chatbotMask
|
|
51
|
+
oswColourBackgroundDark
|
|
52
|
+
oswColourBackgroundLight
|
|
53
|
+
oswColourFontDark
|
|
54
|
+
oswColourFontLight
|
|
55
|
+
oswHintMessage
|
|
56
|
+
oswLabel
|
|
57
|
+
position
|
|
58
|
+
showNotification
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
`;
|
|
63
|
+
|
|
64
|
+
const response = await fetch(graphqlUrl, {
|
|
65
|
+
method: "POST",
|
|
66
|
+
headers: {
|
|
67
|
+
"Content-Type": "application/json",
|
|
68
|
+
"Accept-Language": language,
|
|
69
|
+
},
|
|
70
|
+
body: JSON.stringify({ query }),
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
console.log(
|
|
74
|
+
"[OSW Widget] Response status:",
|
|
75
|
+
response.status,
|
|
76
|
+
response.statusText
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
if (!response.ok) {
|
|
80
|
+
console.error(
|
|
81
|
+
"[OSW Widget] Failed to fetch - Status:",
|
|
82
|
+
response.status,
|
|
83
|
+
response.statusText
|
|
84
|
+
);
|
|
85
|
+
const errorText = await response
|
|
86
|
+
.text()
|
|
87
|
+
.catch(() => "Unable to read error response");
|
|
88
|
+
console.error("[OSW Widget] Error response:", errorText);
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const result = await response.json();
|
|
93
|
+
console.log("[OSW Widget] GraphQL response:", result);
|
|
94
|
+
|
|
95
|
+
if (result.data?.oswChatbotSettingsPublic?.success) {
|
|
96
|
+
console.log(
|
|
97
|
+
"[OSW Widget] Settings retrieved successfully:",
|
|
98
|
+
result.data.oswChatbotSettingsPublic.settings
|
|
99
|
+
);
|
|
100
|
+
return result.data.oswChatbotSettingsPublic.settings;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
console.warn(
|
|
104
|
+
"[OSW Widget] GraphQL query succeeded but success=false or missing data"
|
|
105
|
+
);
|
|
106
|
+
return null;
|
|
107
|
+
} catch (error) {
|
|
108
|
+
console.error("[OSW Widget] Exception while fetching settings:", error);
|
|
109
|
+
console.error("[OSW Widget] Error details:", error.message, error.stack);
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Default configuration with fallback values
|
|
115
|
+
const defaultConfig = {
|
|
116
|
+
env: "prod",
|
|
117
|
+
width: "414px",
|
|
118
|
+
height: "75vh",
|
|
119
|
+
openText: "Chat",
|
|
120
|
+
closeText: "Close",
|
|
121
|
+
background: "#FEFFFF",
|
|
122
|
+
backgroundDark: "#171717",
|
|
123
|
+
fontColor: "#3c4043",
|
|
124
|
+
fontColorDark: "#FFFFFF",
|
|
125
|
+
position: "right",
|
|
126
|
+
animation: "none",
|
|
127
|
+
shakeDuration: 3000,
|
|
128
|
+
shakeInterval: 1000,
|
|
129
|
+
shakeAmplitude: 10,
|
|
130
|
+
shakeFrequency: 1,
|
|
131
|
+
showNotification: false,
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
// Initial config from HTML attributes with fallback to defaults
|
|
135
|
+
const config = {
|
|
136
|
+
src: wrapper.getAttribute("src"),
|
|
137
|
+
orgId: wrapper.getAttribute("orgId"),
|
|
138
|
+
env: wrapper.getAttribute("env") || defaultConfig.env,
|
|
139
|
+
width: wrapper.getAttribute("width") || defaultConfig.width,
|
|
140
|
+
height: wrapper.getAttribute("height") || defaultConfig.height,
|
|
141
|
+
openText: wrapper.getAttribute("openText") || defaultConfig.openText,
|
|
142
|
+
closeText: wrapper.getAttribute("closeText") || defaultConfig.closeText,
|
|
143
|
+
background: wrapper.getAttribute("background") || defaultConfig.background,
|
|
144
|
+
backgroundDark:
|
|
145
|
+
wrapper.getAttribute("backgroundDark") || defaultConfig.backgroundDark,
|
|
146
|
+
fontColor: wrapper.getAttribute("fontColor") || defaultConfig.fontColor,
|
|
147
|
+
fontColorDark:
|
|
148
|
+
wrapper.getAttribute("fontColorDark") || defaultConfig.fontColorDark,
|
|
149
|
+
logo: wrapper.getAttribute("logo"),
|
|
150
|
+
logoDark: wrapper.getAttribute("logoDark"),
|
|
151
|
+
position: wrapper.getAttribute("position") || defaultConfig.position,
|
|
152
|
+
animation: wrapper.getAttribute("animation") || defaultConfig.animation,
|
|
153
|
+
shakeDuration:
|
|
154
|
+
parseInt(wrapper.getAttribute("shakeDuration")) ||
|
|
155
|
+
defaultConfig.shakeDuration,
|
|
156
|
+
shakeInterval:
|
|
157
|
+
parseInt(wrapper.getAttribute("shakeInterval")) ||
|
|
158
|
+
defaultConfig.shakeInterval,
|
|
159
|
+
shakeAmplitude:
|
|
160
|
+
parseInt(wrapper.getAttribute("shakeAmplitude")) ||
|
|
161
|
+
defaultConfig.shakeAmplitude,
|
|
162
|
+
shakeFrequency:
|
|
163
|
+
parseInt(wrapper.getAttribute("shakeFrequency")) ||
|
|
164
|
+
defaultConfig.shakeFrequency,
|
|
165
|
+
showNotification:
|
|
166
|
+
wrapper.getAttribute("showNotification") === "true" ||
|
|
167
|
+
defaultConfig.showNotification,
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
const origin = config.src.substring(0, config.src.lastIndexOf("/"));
|
|
171
|
+
|
|
172
|
+
// Get detected language
|
|
173
|
+
const detectedLang = getLanguage();
|
|
174
|
+
console.log("[OSW Widget] Detected language:", detectedLang);
|
|
175
|
+
console.log("[OSW Widget] Initial config from HTML:", config);
|
|
176
|
+
|
|
177
|
+
// Fetch settings from GraphQL and merge with config
|
|
178
|
+
if (!config.orgId) {
|
|
179
|
+
console.error(
|
|
180
|
+
"[OSW Widget] No organization ID provided! Widget will not be displayed."
|
|
181
|
+
);
|
|
182
|
+
console.error(
|
|
183
|
+
"[OSW Widget] Add orgId attribute to the script tag: <script id='df-btn' orgId='YOUR_ORG_ID' ...>"
|
|
184
|
+
);
|
|
185
|
+
return; // Exit if no orgId
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
const settings = await fetchChatbotSettings(
|
|
189
|
+
config.orgId,
|
|
190
|
+
config.env,
|
|
191
|
+
detectedLang
|
|
192
|
+
);
|
|
193
|
+
|
|
194
|
+
if (!settings) {
|
|
195
|
+
console.warn(
|
|
196
|
+
"[OSW Widget] Failed to fetch chatbot settings. Using fallback configuration."
|
|
197
|
+
);
|
|
198
|
+
console.warn("[OSW Widget] Check:");
|
|
199
|
+
console.warn("[OSW Widget] 1. Network tab for CORS errors");
|
|
200
|
+
console.warn("[OSW Widget] 2. Organization ID is correct");
|
|
201
|
+
console.warn("[OSW Widget] 3. API endpoint is accessible");
|
|
202
|
+
// Continue with default config instead of exiting
|
|
203
|
+
config.hintMessage = "Click to check messages";
|
|
204
|
+
} else {
|
|
205
|
+
console.log("[OSW Widget] Merging GraphQL settings with config...");
|
|
206
|
+
|
|
207
|
+
// Merge GraphQL settings with config (GraphQL takes precedence, but null values fall back to HTML attributes)
|
|
208
|
+
config.animation = settings.animation || config.animation;
|
|
209
|
+
config.openText = settings.oswLabel || config.openText;
|
|
210
|
+
config.position = settings.position || config.position;
|
|
211
|
+
config.background = settings.oswColourBackgroundLight || config.background;
|
|
212
|
+
config.backgroundDark =
|
|
213
|
+
settings.oswColourBackgroundDark || config.backgroundDark;
|
|
214
|
+
config.fontColor = settings.oswColourFontLight || config.fontColor;
|
|
215
|
+
config.fontColorDark = settings.oswColourFontDark || config.fontColorDark;
|
|
216
|
+
config.showNotification =
|
|
217
|
+
settings.showNotification ?? config.showNotification;
|
|
218
|
+
config.hintMessage = settings.oswHintMessage || "Click to check messages";
|
|
219
|
+
|
|
220
|
+
// Use chatbotMask as logo if available
|
|
221
|
+
if (settings.chatbotMask) {
|
|
222
|
+
config.logo = settings.chatbotMask;
|
|
223
|
+
config.logoDark = settings.chatbotMask;
|
|
224
|
+
console.log(
|
|
225
|
+
"[OSW Widget] Using chatbotMask as logo:",
|
|
226
|
+
settings.chatbotMask
|
|
227
|
+
);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
console.log("[OSW Widget] Final merged config:", config);
|
|
232
|
+
console.log("[OSW Widget] Widget will render with:", {
|
|
233
|
+
animation: config.animation,
|
|
234
|
+
openText: config.openText,
|
|
235
|
+
position: config.position,
|
|
236
|
+
showNotification: config.showNotification,
|
|
237
|
+
logo: config.logo ? "Custom logo" : "Default logo",
|
|
238
|
+
});
|
|
28
239
|
const style = document.createElement("style");
|
|
29
240
|
style.innerHTML = `
|
|
30
241
|
.df-btn {
|
|
@@ -53,8 +264,8 @@ if (!config.orgId) {
|
|
|
53
264
|
position: absolute;
|
|
54
265
|
top: -45px;
|
|
55
266
|
${config.position === "left" ? "left: 0;" : "right: 0;"}
|
|
56
|
-
background: #
|
|
57
|
-
color:
|
|
267
|
+
background: ${config.background || "#FEFFFF"};
|
|
268
|
+
color: ${config.fontColor || "#3c4043"};
|
|
58
269
|
padding: 8px 16px;
|
|
59
270
|
border-radius: 8px;
|
|
60
271
|
font-size: 13px;
|
|
@@ -63,7 +274,10 @@ if (!config.orgId) {
|
|
|
63
274
|
transition: all 0.3s ease;
|
|
64
275
|
white-space: nowrap;
|
|
65
276
|
box-shadow: 0 2px 6px rgba(0,0,0,0.15);
|
|
66
|
-
pointer-events:
|
|
277
|
+
pointer-events: auto;
|
|
278
|
+
display: flex;
|
|
279
|
+
align-items: center;
|
|
280
|
+
gap: 8px;
|
|
67
281
|
}
|
|
68
282
|
|
|
69
283
|
.df-notification:after {
|
|
@@ -75,7 +289,7 @@ if (!config.orgId) {
|
|
|
75
289
|
height: 0;
|
|
76
290
|
border-left: 6px solid transparent;
|
|
77
291
|
border-right: 6px solid transparent;
|
|
78
|
-
border-top: 6px solid #
|
|
292
|
+
border-top: 6px solid ${config.background || "#FEFFFF"};
|
|
79
293
|
}
|
|
80
294
|
|
|
81
295
|
.df-notification.show {
|
|
@@ -83,9 +297,29 @@ if (!config.orgId) {
|
|
|
83
297
|
transform: translateY(0);
|
|
84
298
|
}
|
|
85
299
|
|
|
300
|
+
.df-notification-close {
|
|
301
|
+
cursor: pointer;
|
|
302
|
+
width: 16px;
|
|
303
|
+
height: 16px;
|
|
304
|
+
display: flex;
|
|
305
|
+
align-items: center;
|
|
306
|
+
justify-content: center;
|
|
307
|
+
flex-shrink: 0;
|
|
308
|
+
opacity: 0.7;
|
|
309
|
+
transition: opacity 0.2s ease;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
.df-notification-close:hover {
|
|
313
|
+
opacity: 1;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
.df-notification-text {
|
|
317
|
+
flex: 1;
|
|
318
|
+
}
|
|
319
|
+
|
|
86
320
|
.df-btn-text {
|
|
87
321
|
min-width: 56px;
|
|
88
|
-
color: #3c4043;
|
|
322
|
+
color: ${config.fontColor || "#3c4043"};
|
|
89
323
|
display: inline-flex;
|
|
90
324
|
align-items: center;
|
|
91
325
|
font-weight: 500;
|
|
@@ -106,7 +340,9 @@ if (!config.orgId) {
|
|
|
106
340
|
background-position: center;
|
|
107
341
|
background-repeat: no-repeat;
|
|
108
342
|
background-size: cover;
|
|
109
|
-
background-image: url('${
|
|
343
|
+
background-image: url('${
|
|
344
|
+
config.logo || origin + "/assets/chat-agent.jpg"
|
|
345
|
+
}');
|
|
110
346
|
border-radius: 50%;
|
|
111
347
|
width: 32px;
|
|
112
348
|
height: 32px;
|
|
@@ -249,16 +485,29 @@ if (!config.orgId) {
|
|
|
249
485
|
}
|
|
250
486
|
|
|
251
487
|
.df-btn-text {
|
|
252
|
-
color:
|
|
488
|
+
color: ${config.fontColorDark || "#FFFFFF"}
|
|
253
489
|
}
|
|
254
490
|
|
|
255
491
|
.df-btn-text:before {
|
|
256
|
-
background-image: url('${
|
|
492
|
+
background-image: url('${
|
|
493
|
+
config.logoDark ||
|
|
494
|
+
config.logo ||
|
|
495
|
+
origin + "/assets/chat-agent.jpg"
|
|
496
|
+
}')
|
|
257
497
|
}
|
|
258
498
|
|
|
259
499
|
.df-btn:not(.df-closed) > .df-btn-text:before {
|
|
260
500
|
background-image: url('${origin}/assets/close_dark.svg')
|
|
261
501
|
}
|
|
502
|
+
|
|
503
|
+
.df-notification {
|
|
504
|
+
background: ${config.backgroundDark || "#171717"};
|
|
505
|
+
color: ${config.fontColorDark || "#FFFFFF"};
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
.df-notification:after {
|
|
509
|
+
border-top: 6px solid ${config.backgroundDark || "#171717"};
|
|
510
|
+
}
|
|
262
511
|
}
|
|
263
512
|
|
|
264
513
|
@keyframes shake {
|
|
@@ -280,27 +529,6 @@ if (!config.orgId) {
|
|
|
280
529
|
|
|
281
530
|
document.head.appendChild(style);
|
|
282
531
|
|
|
283
|
-
// Language detection function
|
|
284
|
-
function getLanguage() {
|
|
285
|
-
// Check HTML lang attribute first
|
|
286
|
-
let lang = document.documentElement.lang || "";
|
|
287
|
-
|
|
288
|
-
// Fallback to browser language
|
|
289
|
-
if (!lang) {
|
|
290
|
-
lang = navigator.language || navigator.languages?.[0] || "en";
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
// Extract language code (e.g., "en" from "en-US")
|
|
294
|
-
lang = lang.split("-")[0].toLowerCase();
|
|
295
|
-
|
|
296
|
-
// Validate against supported languages
|
|
297
|
-
const supportedLangs = ["en", "de", "it", "fr", "es"];
|
|
298
|
-
return supportedLangs.includes(lang) ? lang : "de";
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
// Get the detected language
|
|
302
|
-
const detectedLang = getLanguage();
|
|
303
|
-
|
|
304
532
|
// Function to get chat URL based on environment
|
|
305
533
|
function getChatUrl() {
|
|
306
534
|
const env = config.env;
|
|
@@ -316,11 +544,21 @@ if (!config.orgId) {
|
|
|
316
544
|
}
|
|
317
545
|
}
|
|
318
546
|
|
|
319
|
-
|
|
547
|
+
// Create button HTML
|
|
548
|
+
const buttonHTML = `
|
|
320
549
|
<button class="df-btn df-closed" onclick="dfToggle()">
|
|
321
550
|
${
|
|
322
551
|
config.showNotification
|
|
323
|
-
?
|
|
552
|
+
? `<div class="df-notification">
|
|
553
|
+
<span class="df-notification-text">${
|
|
554
|
+
config.hintMessage || "Click to check messages"
|
|
555
|
+
}</span>
|
|
556
|
+
<div class="df-notification-close" onclick="dismissNotification(event)">
|
|
557
|
+
<svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor">
|
|
558
|
+
<path d="M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708z"/>
|
|
559
|
+
</svg>
|
|
560
|
+
</div>
|
|
561
|
+
</div>`
|
|
324
562
|
: ""
|
|
325
563
|
}
|
|
326
564
|
<div class="df-btn-header">
|
|
@@ -330,13 +568,63 @@ if (!config.orgId) {
|
|
|
330
568
|
config.orgId
|
|
331
569
|
}" allow="microphone *"></iframe>
|
|
332
570
|
</button>
|
|
333
|
-
|
|
571
|
+
`;
|
|
572
|
+
|
|
573
|
+
// Insert button into DOM (works in async context unlike document.write)
|
|
574
|
+
document.body.insertAdjacentHTML("beforeend", buttonHTML);
|
|
334
575
|
|
|
335
576
|
let dfToggled = false;
|
|
336
577
|
let inactivityTimer = null;
|
|
337
578
|
let shakeInterval = null;
|
|
338
579
|
|
|
580
|
+
// Check if notification was dismissed
|
|
581
|
+
const NOTIFICATION_DISMISSED_KEY = `osw-notification-dismissed-${config.orgId}`;
|
|
582
|
+
|
|
583
|
+
function isNotificationDismissed() {
|
|
584
|
+
try {
|
|
585
|
+
return localStorage.getItem(NOTIFICATION_DISMISSED_KEY) === "true";
|
|
586
|
+
} catch (e) {
|
|
587
|
+
return false;
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
function dismissNotification(event) {
|
|
592
|
+
event.stopPropagation();
|
|
593
|
+
event.preventDefault();
|
|
594
|
+
|
|
595
|
+
const notification = document.querySelector(".df-notification");
|
|
596
|
+
if (notification) {
|
|
597
|
+
notification.classList.remove("show");
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
// Stop any ongoing shake animation
|
|
601
|
+
const button = document.querySelector(".df-btn");
|
|
602
|
+
if (button) {
|
|
603
|
+
button.classList.remove("shake");
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
// Clear timers
|
|
607
|
+
clearInactivityAndShake();
|
|
608
|
+
|
|
609
|
+
// Store dismissed state
|
|
610
|
+
try {
|
|
611
|
+
localStorage.setItem(NOTIFICATION_DISMISSED_KEY, "true");
|
|
612
|
+
} catch (e) {
|
|
613
|
+
console.warn(
|
|
614
|
+
"[OSW Widget] Could not save notification dismissed state:",
|
|
615
|
+
e
|
|
616
|
+
);
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
window.dismissNotification = dismissNotification;
|
|
621
|
+
|
|
339
622
|
const startInactivityTimer = () => {
|
|
623
|
+
// Don't start timer if notification was dismissed
|
|
624
|
+
if (isNotificationDismissed()) {
|
|
625
|
+
return;
|
|
626
|
+
}
|
|
627
|
+
|
|
340
628
|
// Only start inactivity timer if button is closed
|
|
341
629
|
if (!dfToggled) {
|
|
342
630
|
inactivityTimer = setTimeout(() => {
|
|
@@ -518,6 +806,28 @@ if (!config.orgId) {
|
|
|
518
806
|
btn.addEventListener("click", () => {
|
|
519
807
|
// Only toggle if chat is closed (popover mode)
|
|
520
808
|
if (btn.classList.contains("df-closed")) {
|
|
809
|
+
// Dismiss notification when opening chat
|
|
810
|
+
const notification = document.querySelector(".df-notification");
|
|
811
|
+
if (notification && notification.classList.contains("show")) {
|
|
812
|
+
notification.classList.remove("show");
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
// Stop any ongoing shake animation
|
|
816
|
+
btn.classList.remove("shake");
|
|
817
|
+
|
|
818
|
+
// Clear timers
|
|
819
|
+
clearInactivityAndShake();
|
|
820
|
+
|
|
821
|
+
// Store dismissed state
|
|
822
|
+
try {
|
|
823
|
+
localStorage.setItem(NOTIFICATION_DISMISSED_KEY, "true");
|
|
824
|
+
} catch (e) {
|
|
825
|
+
console.warn(
|
|
826
|
+
"[OSW Widget] Could not save notification dismissed state:",
|
|
827
|
+
e
|
|
828
|
+
);
|
|
829
|
+
}
|
|
830
|
+
|
|
521
831
|
const isMobile = window.innerWidth <= 768;
|
|
522
832
|
|
|
523
833
|
if (isMobile) {
|
|
@@ -587,4 +897,6 @@ if (!config.orgId) {
|
|
|
587
897
|
if (!isMobile) {
|
|
588
898
|
startInactivityTimer();
|
|
589
899
|
}
|
|
590
|
-
|
|
900
|
+
|
|
901
|
+
console.log("[OSW Widget] ✓ Widget initialized successfully!");
|
|
902
|
+
})();
|