@xapp/chat-widget 1.54.3 → 1.55.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.
package/dist/index.js CHANGED
@@ -164,6 +164,13 @@ function insertSorted(array, obj, comparer) {
164
164
  return array;
165
165
  }
166
166
 
167
+ /**
168
+ * Agent is determined if the provided nick string starts with `agent:`.
169
+ *
170
+ * This returns false if the nick string is falsey (undefined or "") or does not start with "agent:"
171
+ * @param nick
172
+ * @returns
173
+ */
167
174
  function isAgent(nick) {
168
175
  if (!nick) {
169
176
  return false;
@@ -1552,37 +1559,65 @@ var logOnce = function (key) {
1552
1559
  }
1553
1560
  };
1554
1561
 
1555
- function getVisitorSvg() {
1556
- return (React__default$1["default"].createElement("svg", { width: "16", height: "19", viewBox: "0 0 16 19", style: { margin: "0 auto", display: "block" } },
1557
- React__default$1["default"].createElement("path", { d: "M11.5 5c0-1.933-1.567-3.5-3.5-3.5S4.5 3.067 4.5 5 6.067 8.5 8 8.5s3.5-1.567 3.5-3.5zM3 5c0-2.76 2.24-5 5-5s5 2.24 5 5-2.24 5-5 5-5-2.24-5-5zM1.955 17.294c.21-.642.504-1.285.898-1.88C3.963 13.74 5.615 12.75 8 12.75c2.385 0 4.038.99 5.147 2.664.394.595.69 1.238.898 1.88.124.382.19.672.214.822.063.41.447.69.856.625.41-.063.69-.447.625-.856-.034-.225-.118-.59-.27-1.053-.247-.763-.598-1.527-1.073-2.244C13.024 12.51 10.917 11.25 8 11.25c-2.916 0-5.024 1.26-6.397 3.336-.475.717-.826 1.48-1.074 2.245-.152.463-.236.83-.27 1.054-.065.41.215.793.624.857.41.065.793-.215.857-.624.025-.15.09-.44.215-.822z", fill: "#FFF", fillRule: "evenodd" })));
1558
- }
1559
1562
  var Avatar = function (props) {
1560
1563
  var _a, _b;
1561
1564
  var style = {};
1562
1565
  var child;
1563
1566
  var entity = props.entity;
1567
+ var chatConfig = React$1.useContext(ChatConfigContext);
1564
1568
  var avatarPath = entity === null || entity === void 0 ? void 0 : entity.avatarPath;
1569
+ if (!avatarPath) {
1570
+ var avatarImage = GenerateAvatar({
1571
+ initials: (entity === null || entity === void 0 ? void 0 : entity.displayName) ? entity.displayName.slice(0, 2) : "?",
1572
+ backgroundColor: (_b = (_a = chatConfig === null || chatConfig === void 0 ? void 0 : chatConfig.env) === null || _a === void 0 ? void 0 : _a.theme) === null || _b === void 0 ? void 0 : _b.primaryColor,
1573
+ size: 36,
1574
+ });
1575
+ avatarPath = avatarImage.src;
1576
+ }
1565
1577
  var agentAva = entity && isAgent(entity.nick);
1566
- var ctx = React$1.useContext(ChatConfigContext);
1567
1578
  if (agentAva) {
1568
- if (avatarPath) {
1569
- // absolute or relative url (chat server may send relative, if it hosts the file)
1570
- if (avatarPath.startsWith("http")) {
1571
- style.backgroundImage = "url('".concat(avatarPath, "')");
1572
- }
1573
- else if (ctx === null || ctx === void 0 ? void 0 : ctx.assetUrl) {
1574
- style.backgroundImage = "url('".concat(ctx === null || ctx === void 0 ? void 0 : ctx.assetUrl, "/").concat(avatarPath, "')");
1575
- }
1576
- style.backgroundColor = "none";
1577
- }
1578
- (_a = style.backgroundImage) !== null && _a !== void 0 ? _a : (style.backgroundImage = "url('".concat((_b = ctx === null || ctx === void 0 ? void 0 : ctx.env) === null || _b === void 0 ? void 0 : _b.avatarUrl, "')"));
1579
+ style.backgroundImage = "url('".concat(avatarPath, "')");
1580
+ style.backgroundColor = "none";
1579
1581
  }
1580
1582
  else {
1581
1583
  child = getVisitorSvg();
1582
1584
  }
1583
1585
  var hasImage = !!style.backgroundImage || !!child;
1584
1586
  return (React__default$1["default"].createElement("div", { className: "avatar ".concat(agentAva ? "avatar--agent" : "avatar--visitor", " ").concat(!hasImage ? "avatar--empty" : ""), style: style, title: entity ? entity.display_name : "Agent" }, child));
1585
- };
1587
+ };
1588
+ function getVisitorSvg() {
1589
+ return (React__default$1["default"].createElement("svg", { width: "16", height: "19", viewBox: "0 0 16 19", style: { margin: "0 auto", display: "block" } },
1590
+ React__default$1["default"].createElement("path", { d: "M11.5 5c0-1.933-1.567-3.5-3.5-3.5S4.5 3.067 4.5 5 6.067 8.5 8 8.5s3.5-1.567 3.5-3.5zM3 5c0-2.76 2.24-5 5-5s5 2.24 5 5-2.24 5-5 5-5-2.24-5-5zM1.955 17.294c.21-.642.504-1.285.898-1.88C3.963 13.74 5.615 12.75 8 12.75c2.385 0 4.038.99 5.147 2.664.394.595.69 1.238.898 1.88.124.382.19.672.214.822.063.41.447.69.856.625.41-.063.69-.447.625-.856-.034-.225-.118-.59-.27-1.053-.247-.763-.598-1.527-1.073-2.244C13.024 12.51 10.917 11.25 8 11.25c-2.916 0-5.024 1.26-6.397 3.336-.475.717-.826 1.48-1.074 2.245-.152.463-.236.83-.27 1.054-.065.41.215.793.624.857.41.065.793-.215.857-.624.025-.15.09-.44.215-.822z", fill: "#FFF", fillRule: "evenodd" })));
1591
+ }
1592
+ function GenerateAvatar(props) {
1593
+ var initials = (props === null || props === void 0 ? void 0 : props.initials) || "?";
1594
+ var size = (props === null || props === void 0 ? void 0 : props.size) || 40;
1595
+ var backgroundColor = (props === null || props === void 0 ? void 0 : props.backgroundColor) || "#007bff";
1596
+ var textColor = (props === null || props === void 0 ? void 0 : props.textColor) || "#ffffff";
1597
+ var image = React__default$1["default"].useMemo(function () {
1598
+ return generateImage(initials, size, backgroundColor, textColor);
1599
+ }, [initials, size, backgroundColor, textColor]);
1600
+ return image;
1601
+ }
1602
+ function generateImage(initials, size, backgroundColor, textColor) {
1603
+ var canvas = document.createElement("canvas");
1604
+ canvas.width = size;
1605
+ canvas.height = size;
1606
+ var context = canvas.getContext("2d");
1607
+ // Draw background
1608
+ context.fillStyle = backgroundColor;
1609
+ context.fillRect(0, 0, size, size);
1610
+ // Draw text
1611
+ context.fillStyle = textColor;
1612
+ context.font = "".concat(size / 2, "px Arial");
1613
+ context.textAlign = "center";
1614
+ context.textBaseline = "middle";
1615
+ context.fillText(initials, size / 2, size / 2);
1616
+ // Create image
1617
+ var image = new Image();
1618
+ image.src = canvas.toDataURL();
1619
+ return image;
1620
+ }
1586
1621
 
1587
1622
  function isChatServerActionLink(arg) {
1588
1623
  return arg.hasOwnProperty("label");
@@ -2017,7 +2052,7 @@ function writeMessage(msg, user) {
2017
2052
  type: "write_msg",
2018
2053
  user: user,
2019
2054
  msg: msg,
2020
- timestamp: +Date()
2055
+ timestamp: +new Date()
2021
2056
  }
2022
2057
  };
2023
2058
  }
@@ -2050,7 +2085,7 @@ function receiveToken(token) {
2050
2085
  type: "receiveToken",
2051
2086
  detail: {
2052
2087
  token: token,
2053
- timestamp: +Date(),
2088
+ timestamp: +new Date(),
2054
2089
  type: "receiveToken",
2055
2090
  user: undefined
2056
2091
  }
@@ -2091,7 +2126,7 @@ function sendFile(file) {
2091
2126
  nick: "",
2092
2127
  },
2093
2128
  attributes: { currentUrl: window.location.href },
2094
- timestamp: +Date()
2129
+ timestamp: +new Date()
2095
2130
  }
2096
2131
  });
2097
2132
  }; };
@@ -3793,7 +3828,7 @@ var StentorRouterChat = /** @class */ (function () {
3793
3828
  this.dispatch = dispatch;
3794
3829
  this.setAccountStatus("offline");
3795
3830
  // Register "handlers" for the incoming events
3796
- this.handlers["connection update"] = function (data, _sender) {
3831
+ this.handlers["connection update"] = function (data, _sender, _ts) {
3797
3832
  log("Connection update received. Session created: ".concat(data.sessionCreated, " Error: ").concat(data.errorMessage || ""));
3798
3833
  if (data.sessionCreated) {
3799
3834
  _this.sessionCreated = true;
@@ -3804,21 +3839,21 @@ var StentorRouterChat = /** @class */ (function () {
3804
3839
  _this.dispatch(setConnectionStatus("offline"));
3805
3840
  }
3806
3841
  };
3807
- this.handlers["account status"] = function (_data, _sender) {
3842
+ this.handlers["account status"] = function (_data, _sender, ts) {
3808
3843
  dispatch({
3809
3844
  type: "account_status",
3810
3845
  detail: {
3811
3846
  status: "online",
3812
- timestamp: +new Date(),
3847
+ timestamp: ts || new Date().getTime(),
3813
3848
  },
3814
3849
  });
3815
3850
  };
3816
- this.handlers["failure"] = function (data, sender) {
3851
+ this.handlers["failure"] = function (data, sender, _ts) {
3817
3852
  err("Router says something failed: type: ".concat(data.type, " tries: ").concat(data.tries, " error: ").concat(data.error));
3818
3853
  var _a = _this.configurableMessages[data.tries], retry = _a.retry, delay = _a.delay, text = _a.text;
3819
3854
  _this.sendFailureMessage(retry, data.delay || delay, text, sender);
3820
3855
  };
3821
- this.handlers["new message"] = function (data, sender) {
3856
+ this.handlers["new message"] = function (data, sender, ts) {
3822
3857
  // Because the router's internal message format is Stentor channel compatible.
3823
3858
  // So the data is either a stentor Request (from widget) or a stentor Response (from bot)
3824
3859
  var _a;
@@ -3844,11 +3879,11 @@ var StentorRouterChat = /** @class */ (function () {
3844
3879
  nick: senderToNick(sender),
3845
3880
  },
3846
3881
  msg: message.msg,
3847
- timestamp: +new Date(),
3882
+ timestamp: ts || new Date().getTime(),
3848
3883
  },
3849
3884
  });
3850
3885
  };
3851
- this.handlers["user joined"] = function (_data, sender) {
3886
+ this.handlers["user joined"] = function (_data, sender, ts) {
3852
3887
  _this.dispatch({
3853
3888
  type: "chat",
3854
3889
  detail: {
@@ -3858,11 +3893,11 @@ var StentorRouterChat = /** @class */ (function () {
3858
3893
  nick: senderToNick(sender),
3859
3894
  avatarPath: sender.avatarPath,
3860
3895
  },
3861
- timestamp: +new Date(),
3896
+ timestamp: ts || new Date().getTime(),
3862
3897
  },
3863
3898
  });
3864
3899
  };
3865
- this.handlers["user left"] = function (_data, sender) {
3900
+ this.handlers["user left"] = function (_data, sender, ts) {
3866
3901
  _this.dispatch({
3867
3902
  type: "chat",
3868
3903
  detail: {
@@ -3871,11 +3906,11 @@ var StentorRouterChat = /** @class */ (function () {
3871
3906
  displayName: sender.displayName,
3872
3907
  nick: senderToNick(sender),
3873
3908
  },
3874
- timestamp: +new Date(),
3909
+ timestamp: ts || new Date().getTime(),
3875
3910
  },
3876
3911
  });
3877
3912
  };
3878
- this.handlers["typing"] = function (_data, sender) {
3913
+ this.handlers["typing"] = function (_data, sender, ts) {
3879
3914
  _this.dispatch({
3880
3915
  type: "chat",
3881
3916
  detail: {
@@ -3884,11 +3919,11 @@ var StentorRouterChat = /** @class */ (function () {
3884
3919
  nick: senderToNick(sender),
3885
3920
  },
3886
3921
  typing: true,
3887
- timestamp: +new Date(),
3922
+ timestamp: ts || new Date().getTime(),
3888
3923
  },
3889
3924
  });
3890
3925
  };
3891
- this.handlers["stop typing"] = function (_data, sender) {
3926
+ this.handlers["stop typing"] = function (_data, sender, ts) {
3892
3927
  _this.dispatch({
3893
3928
  type: "chat",
3894
3929
  detail: {
@@ -3897,7 +3932,7 @@ var StentorRouterChat = /** @class */ (function () {
3897
3932
  nick: senderToNick(sender),
3898
3933
  },
3899
3934
  typing: false,
3900
- timestamp: +new Date(),
3935
+ timestamp: ts || new Date().getTime(),
3901
3936
  },
3902
3937
  });
3903
3938
  };
@@ -3962,7 +3997,7 @@ var StentorRouterChat = /** @class */ (function () {
3962
3997
  var message = JSON.parse(me.data);
3963
3998
  var handler = _this.handlers[message.event];
3964
3999
  if (handler) {
3965
- _this.handlers[message.event](message.data, message.sender);
4000
+ _this.handlers[message.event](message.data, message.sender, message.timeMs);
3966
4001
  }
3967
4002
  else {
3968
4003
  log("Unknown router message event: ".concat(message.event));
@@ -7759,6 +7794,7 @@ var StentorServerChat = /** @class */ (function () {
7759
7794
  return StentorServerChat;
7760
7795
  }());
7761
7796
 
7797
+ // import { useWhatChanged } from '@simbathesailor/use-what-changed';
7762
7798
  function createChatServerCore(config, options) {
7763
7799
  switch (config.type) {
7764
7800
  case "direct":
@@ -7787,6 +7823,9 @@ var ChatServerContext = React$1.createContext(null);
7787
7823
  function useChatServer(config, options) {
7788
7824
  var _a = React$1.useState(), server = _a[0], setServer = _a[1];
7789
7825
  var dispatch = useChatDispatch();
7826
+ var deps = [options, config, dispatch];
7827
+ // Log what caused the "effect"
7828
+ // useWhatChanged(deps, "options, config, dispatch");
7790
7829
  React$1.useEffect(function () {
7791
7830
  var newServer = createChatServer(config, options);
7792
7831
  newServer.init(dispatch);
@@ -7794,7 +7833,7 @@ function useChatServer(config, options) {
7794
7833
  return function () {
7795
7834
  newServer.dispose();
7796
7835
  };
7797
- }, [options, config, dispatch]);
7836
+ }, deps);
7798
7837
  return server;
7799
7838
  }
7800
7839
 
@@ -8541,30 +8580,41 @@ var ChatMessage = function (props) {
8541
8580
  /**
8542
8581
  * value must be like "60m", "2h" etc.
8543
8582
  */
8544
- function convertToSeconds(value) {
8545
- var unit = value === null || value === void 0 ? void 0 : value.slice(-1);
8546
- var number = parseFloat(value === null || value === void 0 ? void 0 : value.slice(0, -1));
8583
+ function convertToSeconds(s) {
8584
+ if (!s) {
8585
+ return 0;
8586
+ }
8587
+ var groups = s.match(/(\d+)([dhms]?)/);
8588
+ if (!groups) {
8589
+ err("Invalid time string: ".concat(s));
8590
+ return 0;
8591
+ }
8592
+ var number = parseInt(groups[1]);
8593
+ var unit = groups[2];
8547
8594
  switch (unit) {
8548
- case "d": {
8595
+ case "d":
8549
8596
  return number * 24 * 60 * 60;
8550
- }
8551
- case "h": {
8597
+ case "h":
8552
8598
  return number * 60 * 60;
8553
- }
8554
- case "m": {
8599
+ case "m":
8555
8600
  return number * 60;
8556
- }
8557
- case "s": {
8601
+ case "s":
8558
8602
  return number;
8559
- }
8560
- default: {
8603
+ default:
8604
+ // seconds (no unit)
8561
8605
  return number;
8562
- }
8563
8606
  }
8564
8607
  }
8565
8608
 
8566
- function checkSessionExpiration(duration, lastMessageTimestamp, lastTimestamp) {
8567
- return lastTimestamp - lastMessageTimestamp > convertToSeconds(duration);
8609
+ function checkSessionExpiration(duration, lastMessageTimestamp, _lastTimestamp) {
8610
+ var durationMs = convertToSeconds(duration) * 1000;
8611
+ // never if no session duration in config
8612
+ if (!duration) {
8613
+ return false;
8614
+ }
8615
+ // TODO: Why? Let's use the time passed since the last message timestamp
8616
+ // return lastTimestamp - lastMessageTimestamp > durationMs;
8617
+ return +new Date() - lastMessageTimestamp > durationMs;
8568
8618
  }
8569
8619
 
8570
8620
  function useExternalScript(url) {
@@ -31384,14 +31434,17 @@ var TypingIndicator = function (_) {
31384
31434
  */
31385
31435
  var TypingStatus = function (props) {
31386
31436
  var agentsTyping = Object.values(props.agents).filter(function (agent) { return agent.typing; });
31387
- return (React__default$1["default"].createElement(React__default$1["default"].Fragment, null, agentsTyping.map(function (agent) {
31437
+ return (React__default$1["default"].createElement(React__default$1["default"].Fragment, null, agentsTyping.map(function (agent, index) {
31388
31438
  var _a, _b;
31389
- return (React__default$1["default"].createElement(React__default$1["default"].Fragment, null, !props.textTypingStatusEnabled ? (React__default$1["default"].createElement("div", { className: "chat-msg-container-wrapper", key: "typing-status-".concat(agent.user.nick) },
31390
- React__default$1["default"].createElement("div", { key: agent.user.nick, className: "chat-msg-container agent chat-typing-progress" },
31439
+ var key = ((_a = agent.user) === null || _a === void 0 ? void 0 : _a.nick) || "".concat(index);
31440
+ var displayName = ((_b = agent.user) === null || _b === void 0 ? void 0 : _b.displayName) || "Somebody";
31441
+ return (React__default$1["default"].createElement(React__default$1["default"].Fragment, null, !props.textTypingStatusEnabled ? (React__default$1["default"].createElement("div", { className: "chat-msg-container-wrapper", key: "typing-status-".concat(key) },
31442
+ React__default$1["default"].createElement("div", { key: key, className: "chat-msg-container agent chat-typing-progress" },
31391
31443
  React__default$1["default"].createElement(ChatMessagePart, { user: agent.user, showAvatar: true },
31392
31444
  React__default$1["default"].createElement("div", { className: "chat-msg" },
31393
31445
  React__default$1["default"].createElement(ChatMessageBubble, { owner: "others", hasTail: true },
31394
- React__default$1["default"].createElement(TypingIndicator, null))))))) : (React__default$1["default"].createElement("div", { key: "typing-status-".concat(agent.user.nick), className: "chat-msg-agent-typing" }, (_b = (_a = agent.user) === null || _a === void 0 ? void 0 : _a.displayName) !== null && _b !== void 0 ? _b : "Somebody",
31446
+ React__default$1["default"].createElement(TypingIndicator, null))))))) : (React__default$1["default"].createElement("div", { key: "typing-status-".concat(key), className: "chat-msg-agent-typing" },
31447
+ displayName,
31395
31448
  " is typing"))));
31396
31449
  })));
31397
31450
  };
@@ -31449,7 +31502,7 @@ var MessageList = function (props) {
31449
31502
  user = ((_a = props.agents[msg.user.nick]) === null || _a === void 0 ? void 0 : _a.user) || props.agent;
31450
31503
  // Still nothing?
31451
31504
  if (!user) {
31452
- console.warn("Could not get a user from agents list with nick: \"".concat(msg.user.nick, "\""));
31505
+ log("Could not get a user from agents list with nick: \"".concat(msg.user.nick, "\""));
31453
31506
  user = msg.user;
31454
31507
  }
31455
31508
  }
@@ -31483,7 +31536,14 @@ var MessageList = function (props) {
31483
31536
  *
31484
31537
  */
31485
31538
  function renderAll() {
31486
- return props.messages.map(function (message /*, index: number*/) {
31539
+ var lastMsgIndex = -1;
31540
+ for (var i = props.messages.length - 1; i > 0; i--) {
31541
+ if (props.messages[i].type === "chat.msg") {
31542
+ lastMsgIndex = i;
31543
+ break;
31544
+ }
31545
+ }
31546
+ return props.messages.map(function (message, index) {
31487
31547
  // const next = props.messages[index + 1];
31488
31548
  // let sibling = false;
31489
31549
  // const currentNick = message.nick;
@@ -31492,7 +31552,37 @@ var MessageList = function (props) {
31492
31552
  // if (next && next.type === message.type && currentNick && currentNick === prevNick) {
31493
31553
  // sibling = true;
31494
31554
  // }
31495
- return renderByType(message, false);
31555
+ // Message types that will show time
31556
+ var tsTypes = [
31557
+ "chat.file",
31558
+ "chat.msg",
31559
+ // "chat.failureMsg",
31560
+ "chat.memberjoin",
31561
+ "chat.memberleave",
31562
+ "chat.rating",
31563
+ // "chat.typing",
31564
+ "chat.request.rating",
31565
+ "chat.offline",
31566
+ "chat.prechat"
31567
+ ];
31568
+ // show first and las TS and after at least 5 minutes gap
31569
+ var showTs = false;
31570
+ if (tsTypes.includes(message.type)) {
31571
+ if (index === 0 || index === props.messages.length - 1 || index === lastMsgIndex) {
31572
+ showTs = true;
31573
+ }
31574
+ else {
31575
+ var previous = props.messages[index - 1];
31576
+ if (message.timestamp && previous.timestamp) {
31577
+ showTs = (message.timestamp - previous.timestamp) > 300 * 1000; // 5 minutes
31578
+ }
31579
+ }
31580
+ }
31581
+ var ts = showTs ? new Date(message.timestamp).toLocaleString() : undefined;
31582
+ return (React__default$1["default"].createElement(React__default$1["default"].Fragment, null,
31583
+ showTs && (React__default$1["default"].createElement("div", { className: "ts-msg-container" },
31584
+ React__default$1["default"].createElement("span", { className: "ts-msg" }, ts))),
31585
+ renderByType(message, false)));
31496
31586
  });
31497
31587
  }
31498
31588
  var agents = props.agents, queuePosition = props.queuePosition;
@@ -31546,9 +31636,9 @@ var refreshButtonAriaLabel = "To refresh chat click on clockwise gapped circle a
31546
31636
  var minimizeButtonAriaLabel = "To minimize widget click on minus icon in top right side of widget. ";
31547
31637
  var closeButtonAriaLabel = "To close widget click on close icon in top right side of widget.";
31548
31638
  var ChatHeader = function (props) {
31549
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
31639
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r;
31550
31640
  var menuConfig = props.menuConfig, onSubmit = props.onSubmit;
31551
- var _q = React$1.useState(false), drawerOpen = _q[0], setDrawerState = _q[1]; // false initially
31641
+ var _s = React$1.useState(false), drawerOpen = _s[0], setDrawerState = _s[1]; // false initially
31552
31642
  var menuPosition = (menuConfig === null || menuConfig === void 0 ? void 0 : menuConfig.menuButtonLocation) || "FOOTER";
31553
31643
  var showMenu = menuPosition === "HEADER_LEFT";
31554
31644
  var menuItemsRaw = menuConfig === null || menuConfig === void 0 ? void 0 : menuConfig.items; // useWidgetEnv()?.menu?.items;
@@ -31569,16 +31659,15 @@ var ChatHeader = function (props) {
31569
31659
  showMenu && menuItems.length ? (React__default$1["default"].createElement(React__default$1["default"].Fragment, null,
31570
31660
  React__default$1["default"].createElement("div", { className: "chat-footer__menu-icon" },
31571
31661
  React__default$1["default"].createElement(DrawerBars, { bars: 3, tabIndex: menuButtonTabIndex, onToggle: toggleDrawer })))) : React__default$1["default"].createElement(React__default$1["default"].Fragment, null),
31572
- React__default$1["default"].createElement("div", { className: "status-container__avatar" },
31573
- React__default$1["default"].createElement(Avatar, { entity: props.agent })),
31574
- React__default$1["default"].createElement("div", { className: "".concat("status-text", " ").concat(((_b = props.config) === null || _b === void 0 ? void 0 : _b.alignTextCenter)
31575
- ? "status-text-positionCenter"
31576
- : "status-text-positionLeft") },
31577
- React__default$1["default"].createElement("span", { className: "status-text-title" }, getStatusText(props.accountStatus, (_c = props.config) === null || _c === void 0 ? void 0 : _c.status)),
31578
- ((_e = (_d = props.config) === null || _d === void 0 ? void 0 : _d.subtitle) === null || _e === void 0 ? void 0 : _e.enabled) && (React__default$1["default"].createElement("span", { className: "status-text-subtitle" }, (_h = (_g = (_f = props.config) === null || _f === void 0 ? void 0 : _f.subtitle) === null || _g === void 0 ? void 0 : _g.text) !== null && _h !== void 0 ? _h : ""))),
31579
- props.canRefresh && (React__default$1["default"].createElement(RefreshButton, { onClick: props.refreshOnClick, tabIndex: (_k = (_j = props.config) === null || _j === void 0 ? void 0 : _j.actions) === null || _k === void 0 ? void 0 : _k.refreshTabIndex, showInLeft: props.canMinimize && props.canCancel, showInRight: !props.canMinimize && !props.canCancel })),
31580
- props.canMinimize && (React__default$1["default"].createElement(MinimizeButton, { onClick: props.minimizeOnClick, tabIndex: (_m = (_l = props.config) === null || _l === void 0 ? void 0 : _l.actions) === null || _m === void 0 ? void 0 : _m.minimizeTabIndex, showInRight: !props.canCancel })),
31581
- props.canCancel && (React__default$1["default"].createElement(CancelButton, { onClick: props.cancelOnClick, tabIndex: (_p = (_o = props.config) === null || _o === void 0 ? void 0 : _o.actions) === null || _p === void 0 ? void 0 : _p.cancelTabIndex }))),
31662
+ ((_b = props === null || props === void 0 ? void 0 : props.agent) === null || _b === void 0 ? void 0 : _b.avatarPath) === undefined ? React__default$1["default"].createElement("div", null) :
31663
+ React__default$1["default"].createElement("div", { className: "status-container__avatar" },
31664
+ React__default$1["default"].createElement(Avatar, { entity: props.agent })),
31665
+ React__default$1["default"].createElement("div", { className: "\n ".concat("status-text", "\n ").concat(((_c = props === null || props === void 0 ? void 0 : props.agent) === null || _c === void 0 ? void 0 : _c.avatarPath) === undefined ? "status-text-positionLeftNoAvatar" : "status-text-positionLeft", "\n ").concat(((_d = props.config) === null || _d === void 0 ? void 0 : _d.alignTextCenter) ? "status-text-positionCenter" : "status-text-positionLeft", " \n ") },
31666
+ React__default$1["default"].createElement("span", { className: "status-text-title" }, getStatusText(props.accountStatus, (_e = props.config) === null || _e === void 0 ? void 0 : _e.status)),
31667
+ ((_g = (_f = props.config) === null || _f === void 0 ? void 0 : _f.subtitle) === null || _g === void 0 ? void 0 : _g.enabled) && (React__default$1["default"].createElement("span", { className: "status-text-subtitle" }, (_k = (_j = (_h = props.config) === null || _h === void 0 ? void 0 : _h.subtitle) === null || _j === void 0 ? void 0 : _j.text) !== null && _k !== void 0 ? _k : ""))),
31668
+ props.canRefresh && (React__default$1["default"].createElement(RefreshButton, { onClick: props.refreshOnClick, tabIndex: (_m = (_l = props.config) === null || _l === void 0 ? void 0 : _l.actions) === null || _m === void 0 ? void 0 : _m.refreshTabIndex, showInLeft: props.canMinimize && props.canCancel, showInRight: !props.canMinimize && !props.canCancel })),
31669
+ props.canMinimize && (React__default$1["default"].createElement(MinimizeButton, { onClick: props.minimizeOnClick, tabIndex: (_p = (_o = props.config) === null || _o === void 0 ? void 0 : _o.actions) === null || _p === void 0 ? void 0 : _p.minimizeTabIndex, showInRight: !props.canCancel })),
31670
+ props.canCancel && (React__default$1["default"].createElement(CancelButton, { onClick: props.cancelOnClick, tabIndex: (_r = (_q = props.config) === null || _q === void 0 ? void 0 : _q.actions) === null || _r === void 0 ? void 0 : _r.cancelTabIndex }))),
31582
31671
  drawerOpen ? (React__default$1["default"].createElement("div", { className: "xa-chat-menu-container" },
31583
31672
  React__default$1["default"].createElement(ChatMenu, { openFrom: "left", opened: drawerOpen, tabIndex: menuItemsTabIndex, onItemClick: handleMenuItem, items: menuItems }))) : React__default$1["default"].createElement(React__default$1["default"].Fragment, null)));
31584
31673
  };
@@ -31935,7 +32024,7 @@ var ChatWidget = function (props) {
31935
32024
  set$1("visible", newVisible);
31936
32025
  }, [staticMode]);
31937
32026
  React$1.useEffect(function () {
31938
- var _a;
32027
+ var _a, _b;
31939
32028
  document.addEventListener("keydown", function (event) {
31940
32029
  var body = document.getElementsByTagName("body")[0];
31941
32030
  body.tabIndex = -1;
@@ -31943,7 +32032,8 @@ var ChatWidget = function (props) {
31943
32032
  body.focus();
31944
32033
  }
31945
32034
  });
31946
- if (checkSessionExpiration(chatState === null || chatState === void 0 ? void 0 : chatState.sessionExpiration, (_a = chatState === null || chatState === void 0 ? void 0 : chatState.chats[chatState.chats.length - 1]) === null || _a === void 0 ? void 0 : _a.timestamp, chatState === null || chatState === void 0 ? void 0 : chatState.lastTimestamp)) {
32035
+ if (checkSessionExpiration((chatState === null || chatState === void 0 ? void 0 : chatState.sessionExpiration) || ((_a = props.config) === null || _a === void 0 ? void 0 : _a.sessionExpiration), (_b = chatState === null || chatState === void 0 ? void 0 : chatState.chats[chatState.chats.length - 1]) === null || _b === void 0 ? void 0 : _b.timestamp, chatState === null || chatState === void 0 ? void 0 : chatState.lastTimestamp)) {
32036
+ set$1("sessionId", ""); // force new session
31947
32037
  innerDispatch(reset());
31948
32038
  }
31949
32039
  // eslint-disable-next-line react-hooks/exhaustive-deps
@@ -32062,10 +32152,13 @@ var ChatWidget = function (props) {
32062
32152
  }
32063
32153
  }, [connectionStatus, onConnectionStatusChange]);
32064
32154
  useExternalScript((_m = props.config) === null || _m === void 0 ? void 0 : _m.middlewareUrl);
32155
+ // This is a pseudo agent. It represent's the widget (shown in the header avatar for instance)
32156
+ var widgetAgent = ((_o = chatState.agents["agent:robot"]) === null || _o === void 0 ? void 0 : _o.user) || (config === null || config === void 0 ? void 0 : config.agent)
32157
+ || { nick: "agent:robot", avatarPath: config.avatarUrl, display_name: "Agent" };
32065
32158
  return (React__default$1["default"].createElement(React__default$1["default"].Fragment, null,
32066
32159
  React__default$1["default"].createElement("div", { className: "widget-container ".concat(modeClass, " ").concat(getVisibilityClass()) },
32067
32160
  React__default$1["default"].createElement(WidgetStylesheet, { theme: config === null || config === void 0 ? void 0 : config.theme }),
32068
- React__default$1["default"].createElement(ChatHeader, { accountStatus: chatState.accountStatus, refreshOnClick: openModal, minimizeOnClick: minimizeOnClick, cancelOnClick: cancelOnClick, agent: ((_o = chatState.agents["agent:robot"]) === null || _o === void 0 ? void 0 : _o.user) || (config === null || config === void 0 ? void 0 : config.agent), canRefresh: canRefresh, canMinimize: canMinimize, canCancel: canCancel, config: config === null || config === void 0 ? void 0 : config.header, menuConfig: config.menu, onSubmit: handleOnSubmit }),
32161
+ React__default$1["default"].createElement(ChatHeader, { accountStatus: chatState.accountStatus, refreshOnClick: openModal, minimizeOnClick: minimizeOnClick, cancelOnClick: cancelOnClick, agent: widgetAgent, canRefresh: canRefresh, canMinimize: canMinimize, canCancel: canCancel, config: config === null || config === void 0 ? void 0 : config.header, menuConfig: config.menu, onSubmit: handleOnSubmit }),
32069
32162
  React__default$1["default"].createElement(MessageList, { visible: visible, queuePosition: chatState.queuePosition, isChatting: chatState.isChatting, isOffline: isOffline, messages: messages, agents: chatState.agents, agent: config === null || config === void 0 ? void 0 : config.agent, lastRatingRequestTimestamp: chatState.lastRatingRequestTimestamp, hasRating: chatState.hasRating, visitorId: chatState.visitorId, messageMiddleware: props.messageMiddleware, textTypingStatusEnabled: (_q = (_p = props.config) === null || _p === void 0 ? void 0 : _p.typingStatus) === null || _q === void 0 ? void 0 : _q.textTypingStatusEnabled, onSend: handleSendMessage, onWrite: handleWriteMessage, onOpenUrl: handleOpenUrl }),
32070
32163
  React__default$1["default"].createElement("div", { className: "spinner-container ".concat(visible && connectionStatus === "pending" ? "visible" : "") },
32071
32164
  React__default$1["default"].createElement("div", { className: "spinner" })),
@@ -32204,9 +32297,11 @@ function joinMessages(messages, msg) {
32204
32297
  }
32205
32298
 
32206
32299
  function memberJoin(state, detail) {
32207
- if (state.chats.length === 0) {
32208
- set$1("sessionId", "");
32209
- }
32300
+ // TODO: Why?
32301
+ // if (state.chats.length === 0) {
32302
+ // console.log(`######### No chats in member join action`);
32303
+ // set("sessionId", "");
32304
+ // }
32210
32305
  var agents = __assign({}, state.agents);
32211
32306
  var prevAgentInfo = state.agents[detail.user.nick];
32212
32307
  agents[detail.user.nick] = __assign(__assign({}, prevAgentInfo), { user: __assign(__assign({}, detail.user), { displayName: detail.user.displayName || "Agent" }), joined: true, typing: false });
@@ -32333,8 +32428,9 @@ function update(state, action) {
32333
32428
  }
32334
32429
  }
32335
32430
  function mapSynthetic(state, action) {
32431
+ var _a;
32336
32432
  if (state === void 0) { state = DEFAULT_STATE; }
32337
- var newTimestamp = state.lastTimestamp + 1;
32433
+ var newTimestamp = (((_a = action.detail) === null || _a === void 0 ? void 0 : _a.timestamp) || +new Date()) + 1; // state.lastTimestamp + 1;
32338
32434
  switch (action.detail.type) {
32339
32435
  case "write_msg":
32340
32436
  return {