@lilaquadrat/chat 0.1.2 → 0.1.4
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/types/src/composables/useChatVisibility.d.ts +12 -0
- package/dist/types/src/composables/useWebSocket.d.ts +5 -5
- package/dist/types/src/libs/chatSession.d.ts +109 -0
- package/dist/types/src/libs/websocketManager.d.ts +12 -1
- package/dist/types/src/stores/conversations.store.d.ts +7 -1
- package/dist/types/tsconfig.build.tsbuildinfo +1 -1
- package/dist/wc/lilaquadrat-studio-chat.js +633 -198
- package/dist/wc/lilaquadrat-studio-chat.umd.cjs +9 -9
- package/package.json +11 -2
|
@@ -14561,7 +14561,8 @@ const categoryColors = {
|
|
|
14561
14561
|
plugins: "background-color: #3f2d56; color: #FFF",
|
|
14562
14562
|
startup: "background-color: #5A8C99; color: #FFF",
|
|
14563
14563
|
auth: "background-color: #5A8C99; color: #FFF",
|
|
14564
|
-
websocket: "background-color: #5A8C99; color: #FFF"
|
|
14564
|
+
websocket: "background-color: #5A8C99; color: #FFF",
|
|
14565
|
+
session: "background-color: #7a5a99; color: #FFF"
|
|
14565
14566
|
// Add other predefined categories and colors as needed
|
|
14566
14567
|
};
|
|
14567
14568
|
const logger = new Proxy({}, {
|
|
@@ -14841,6 +14842,16 @@ const useUserStore = /* @__PURE__ */ defineStore("user", () => {
|
|
|
14841
14842
|
});
|
|
14842
14843
|
const useMainStore = /* @__PURE__ */ defineStore("main", () => {
|
|
14843
14844
|
const leftTarget = /* @__PURE__ */ ref("conversations");
|
|
14845
|
+
watch(leftTarget, (value) => {
|
|
14846
|
+
try {
|
|
14847
|
+
if (value) {
|
|
14848
|
+
localStorage.setItem("studio-chat:left-target", value);
|
|
14849
|
+
} else {
|
|
14850
|
+
localStorage.removeItem("studio-chat:left-target");
|
|
14851
|
+
}
|
|
14852
|
+
} catch {
|
|
14853
|
+
}
|
|
14854
|
+
});
|
|
14844
14855
|
const mainTarget = /* @__PURE__ */ ref("chat");
|
|
14845
14856
|
const state = /* @__PURE__ */ ref("disconnected");
|
|
14846
14857
|
const fullscreen = /* @__PURE__ */ ref(false);
|
|
@@ -14998,6 +15009,17 @@ const useUsersCacheStore = /* @__PURE__ */ defineStore("usersCache", () => {
|
|
|
14998
15009
|
const useConversationsStore = /* @__PURE__ */ defineStore("conversations", () => {
|
|
14999
15010
|
const conversations = /* @__PURE__ */ ref([]);
|
|
15000
15011
|
const activeConversation = /* @__PURE__ */ ref();
|
|
15012
|
+
watch(activeConversation, (conversation) => {
|
|
15013
|
+
try {
|
|
15014
|
+
const id = conversation?._id ?? conversation?.id;
|
|
15015
|
+
if (id) {
|
|
15016
|
+
localStorage.setItem("studio-chat:active-conversation", id);
|
|
15017
|
+
} else {
|
|
15018
|
+
localStorage.removeItem("studio-chat:active-conversation");
|
|
15019
|
+
}
|
|
15020
|
+
} catch {
|
|
15021
|
+
}
|
|
15022
|
+
});
|
|
15001
15023
|
const unreadConversations = computed(
|
|
15002
15024
|
() => conversations.value.filter((conversation) => conversation.unread)
|
|
15003
15025
|
);
|
|
@@ -15066,16 +15088,35 @@ const useConversationsStore = /* @__PURE__ */ defineStore("conversations", () =>
|
|
|
15066
15088
|
const response = await sdk.conversations.list();
|
|
15067
15089
|
const newConversations = response.data || [];
|
|
15068
15090
|
newConversations.forEach((newConv) => {
|
|
15069
|
-
const
|
|
15091
|
+
const existing = conversations.value.find(
|
|
15070
15092
|
(existingConv) => existingConv._id === newConv._id || existingConv.id === newConv.id && newConv.id
|
|
15071
15093
|
);
|
|
15072
|
-
if (
|
|
15094
|
+
if (existing) {
|
|
15095
|
+
existing.unreadCount = newConv.unreadCount;
|
|
15096
|
+
existing.unread = newConv.unread;
|
|
15097
|
+
existing.lastMessage = newConv.lastMessage;
|
|
15098
|
+
existing.messagesCount = newConv.messagesCount;
|
|
15099
|
+
existing.participant = { ...existing.participant, ...newConv.participant };
|
|
15100
|
+
} else {
|
|
15073
15101
|
conversations.value.push(newConv);
|
|
15074
15102
|
}
|
|
15075
15103
|
useUsersCacheStore().ingest(newConv.participants);
|
|
15076
15104
|
});
|
|
15077
15105
|
updateAllUnread();
|
|
15078
15106
|
}
|
|
15107
|
+
function refreshConversations() {
|
|
15108
|
+
StudioSDK.flushCache("conversations", "list");
|
|
15109
|
+
StudioSDK.flushCache("messages", "list");
|
|
15110
|
+
return getAllConversations();
|
|
15111
|
+
}
|
|
15112
|
+
async function handleReconnect() {
|
|
15113
|
+
await refreshConversations();
|
|
15114
|
+
const active = activeConversation.value;
|
|
15115
|
+
if (active && !active.isNew && active._id) {
|
|
15116
|
+
const messages = await getMessagesFromApi(active._id);
|
|
15117
|
+
addMessagesToConversation(messages, active._id);
|
|
15118
|
+
}
|
|
15119
|
+
}
|
|
15079
15120
|
async function getMessagesFromApi(conversation, beforeId) {
|
|
15080
15121
|
const sdk = new StudioSDK("chat", sdkOptions2());
|
|
15081
15122
|
const response = await sdk.messages.list(conversation, beforeId);
|
|
@@ -15291,6 +15332,8 @@ const useConversationsStore = /* @__PURE__ */ defineStore("conversations", () =>
|
|
|
15291
15332
|
}
|
|
15292
15333
|
return {
|
|
15293
15334
|
getAllConversations,
|
|
15335
|
+
refreshConversations,
|
|
15336
|
+
handleReconnect,
|
|
15294
15337
|
conversations,
|
|
15295
15338
|
unreadConversations,
|
|
15296
15339
|
totalUnreadCount,
|
|
@@ -15333,21 +15376,22 @@ const useConversationsStore = /* @__PURE__ */ defineStore("conversations", () =>
|
|
|
15333
15376
|
};
|
|
15334
15377
|
});
|
|
15335
15378
|
const _hoisted_1$e = { class: "conversations-module" };
|
|
15336
|
-
const _hoisted_2$
|
|
15379
|
+
const _hoisted_2$b = ["onClick"];
|
|
15337
15380
|
const _hoisted_3$6 = { class: "time" };
|
|
15338
|
-
const _hoisted_4$3 = {
|
|
15339
|
-
|
|
15381
|
+
const _hoisted_4$3 = { class: "message-unread-container" };
|
|
15382
|
+
const _hoisted_5$3 = {
|
|
15383
|
+
key: 0,
|
|
15340
15384
|
class: "lastMessage"
|
|
15341
15385
|
};
|
|
15342
|
-
const
|
|
15343
|
-
key:
|
|
15386
|
+
const _hoisted_6$2 = {
|
|
15387
|
+
key: 1,
|
|
15344
15388
|
class: "unread"
|
|
15345
15389
|
};
|
|
15346
|
-
const
|
|
15347
|
-
key:
|
|
15390
|
+
const _hoisted_7$2 = {
|
|
15391
|
+
key: 3,
|
|
15348
15392
|
class: "draft"
|
|
15349
15393
|
};
|
|
15350
|
-
const _sfc_main$
|
|
15394
|
+
const _sfc_main$k = /* @__PURE__ */ defineComponent({
|
|
15351
15395
|
__name: "conversations.module",
|
|
15352
15396
|
setup(__props) {
|
|
15353
15397
|
const conversationsStore = useConversationsStore();
|
|
@@ -15355,14 +15399,13 @@ const _sfc_main$j = /* @__PURE__ */ defineComponent({
|
|
|
15355
15399
|
const userStore = useUserStore();
|
|
15356
15400
|
watch(() => userStore.user, (user) => {
|
|
15357
15401
|
if (!user) return;
|
|
15402
|
+
console.log("set user");
|
|
15358
15403
|
conversationsStore.cleanConversations();
|
|
15359
15404
|
conversationsStore.getAllConversations();
|
|
15360
15405
|
}, { immediate: true });
|
|
15361
15406
|
const conversations = computed(() => {
|
|
15362
15407
|
const safeConversations = hardCopy(conversationsStore.conversations);
|
|
15363
|
-
return safeConversations.sort((a, b) => {
|
|
15364
|
-
return dayjs(a.lastMessage?.history.created).isBefore(dayjs(b.lastMessage?.history.created)) ? 1 : -1;
|
|
15365
|
-
}).map((conversation) => ({
|
|
15408
|
+
return safeConversations.sort((a, b) => dayjs(a.lastMessage?.history.created).isBefore(dayjs(b.lastMessage?.history.created)) ? 1 : -1).map((conversation) => ({
|
|
15366
15409
|
...conversation,
|
|
15367
15410
|
isActive: activeConversation.value?._id === conversation._id && conversation._id || activeConversation.value?.id === conversation.id && conversation.id
|
|
15368
15411
|
}));
|
|
@@ -15401,16 +15444,18 @@ const _sfc_main$j = /* @__PURE__ */ defineComponent({
|
|
|
15401
15444
|
"remove-user": ""
|
|
15402
15445
|
}, null, 8, ["participants"])),
|
|
15403
15446
|
createBaseVNode("span", _hoisted_3$6, toDisplayString$1(unref(dayjs)(conversation.lastMessage?.history.created).fromNow()), 1),
|
|
15404
|
-
|
|
15405
|
-
|
|
15406
|
-
|
|
15407
|
-
|
|
15447
|
+
createBaseVNode("section", _hoisted_4$3, [
|
|
15448
|
+
conversation.lastMessage ? (openBlock(), createElementBlock("p", _hoisted_5$3, toDisplayString$1(conversation.lastMessage.message), 1)) : createCommentVNode("", true),
|
|
15449
|
+
conversation.unread ? (openBlock(), createElementBlock("span", _hoisted_6$2, toDisplayString$1(conversation.unreadCount), 1)) : createCommentVNode("", true)
|
|
15450
|
+
]),
|
|
15451
|
+
conversation.isNew ? (openBlock(), createElementBlock("span", _hoisted_7$2, "draft")) : createCommentVNode("", true)
|
|
15452
|
+
], 10, _hoisted_2$b);
|
|
15408
15453
|
}), 128))
|
|
15409
15454
|
]);
|
|
15410
15455
|
};
|
|
15411
15456
|
}
|
|
15412
15457
|
});
|
|
15413
|
-
const _style_0$
|
|
15458
|
+
const _style_0$g = ".conversations-module[data-v-c7853fe0]{display:grid;grid-auto-rows:max-content}.conversations-module .single-conversation[data-v-c7853fe0]{padding:20px;gap:5px;cursor:pointer;display:grid;grid-template-columns:1fr 1fr}.conversations-module .single-conversation .time[data-v-c7853fe0]{justify-self:end}.conversations-module .single-conversation .message-unread-container[data-v-c7853fe0]{display:grid;grid-column:1 / 3;grid-template-columns:5fr 1fr}.conversations-module .single-conversation .message-unread-container .lastMessage[data-v-c7853fe0]{white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.conversations-module .single-conversation .message-unread-container .unread[data-v-c7853fe0]{align-self:center;justify-self:end;padding:0 4px;border-radius:8px;background-color:var(--scm-color-own);color:#fff;font-size:.8rem}.conversations-module .single-conversation[data-v-c7853fe0]:hover{background-color:var(--scm-color-surface)}.conversations-module .single-conversation.active[data-v-c7853fe0]{background-color:color-mix(in srgb,var(--scm-color-surface) 85%,var(--scm-color-muted))}.conversations-module .single-conversation.support[data-v-c7853fe0]{font-weight:600;border-left:3px solid var(--scm-color-primary)}";
|
|
15414
15459
|
const _export_sfc = (sfc, props) => {
|
|
15415
15460
|
const target = sfc.__vccOpts || sfc;
|
|
15416
15461
|
for (const [key, val] of props) {
|
|
@@ -15418,8 +15463,8 @@ const _export_sfc = (sfc, props) => {
|
|
|
15418
15463
|
}
|
|
15419
15464
|
return target;
|
|
15420
15465
|
};
|
|
15421
|
-
const ConversationsModule = /* @__PURE__ */ _export_sfc(_sfc_main$
|
|
15422
|
-
const _sfc_main$
|
|
15466
|
+
const ConversationsModule = /* @__PURE__ */ _export_sfc(_sfc_main$k, [["styles", [_style_0$g]], ["__scopeId", "data-v-c7853fe0"]]);
|
|
15467
|
+
const _sfc_main$j = /* @__PURE__ */ defineComponent({
|
|
15423
15468
|
__name: "chats.module",
|
|
15424
15469
|
setup(__props) {
|
|
15425
15470
|
const conversationsStore = useConversationsStore();
|
|
@@ -15437,11 +15482,13 @@ class WebSocketManager {
|
|
|
15437
15482
|
retryCount = 0;
|
|
15438
15483
|
retryDelay = 1e3;
|
|
15439
15484
|
retryTimeoutId = null;
|
|
15485
|
+
connectTimeoutId = null;
|
|
15440
15486
|
// Number of active consumers (components/composables) holding the socket
|
|
15441
15487
|
refCount = 0;
|
|
15442
15488
|
onConnectionChange;
|
|
15443
15489
|
heartbeatIntervalId = null;
|
|
15444
15490
|
lastActivity = 0;
|
|
15491
|
+
recoveryListenersInstalled = false;
|
|
15445
15492
|
constructor() {
|
|
15446
15493
|
}
|
|
15447
15494
|
static getInstance() {
|
|
@@ -15472,12 +15519,9 @@ class WebSocketManager {
|
|
|
15472
15519
|
url,
|
|
15473
15520
|
maxRetries = 50,
|
|
15474
15521
|
maxRetryDelay = 3e4,
|
|
15475
|
-
onMessage,
|
|
15476
|
-
onOpen,
|
|
15477
|
-
onClose,
|
|
15478
|
-
onError,
|
|
15479
15522
|
heartbeatIntervalMs = 3e4,
|
|
15480
15523
|
inactivityTimeoutMs = 6e4,
|
|
15524
|
+
connectTimeoutMs = 1e4,
|
|
15481
15525
|
buildPingMessage
|
|
15482
15526
|
} = options;
|
|
15483
15527
|
this.currentOptions = {
|
|
@@ -15486,8 +15530,10 @@ class WebSocketManager {
|
|
|
15486
15530
|
maxRetryDelay,
|
|
15487
15531
|
heartbeatIntervalMs,
|
|
15488
15532
|
inactivityTimeoutMs,
|
|
15533
|
+
connectTimeoutMs,
|
|
15489
15534
|
buildPingMessage
|
|
15490
15535
|
};
|
|
15536
|
+
this.installRecoveryListeners();
|
|
15491
15537
|
if (this.socket && (this.socket.readyState === WebSocket.OPEN || this.socket.readyState === WebSocket.CONNECTING)) {
|
|
15492
15538
|
logger.websocket("WS already connecting/open; reusing existing socket");
|
|
15493
15539
|
return;
|
|
@@ -15496,33 +15542,76 @@ class WebSocketManager {
|
|
|
15496
15542
|
clearTimeout(this.retryTimeoutId);
|
|
15497
15543
|
this.retryTimeoutId = null;
|
|
15498
15544
|
}
|
|
15545
|
+
if (this.socket) this.detachHandlers(this.socket);
|
|
15499
15546
|
const ws = new WebSocket(url);
|
|
15500
15547
|
this.socket = ws;
|
|
15548
|
+
this.clearConnectTimeout();
|
|
15549
|
+
this.connectTimeoutId = setTimeout(() => {
|
|
15550
|
+
if (ws.readyState === WebSocket.CONNECTING) {
|
|
15551
|
+
logger.websocket("connect timeout: handshake not completed, aborting socket");
|
|
15552
|
+
try {
|
|
15553
|
+
ws.close();
|
|
15554
|
+
} catch {
|
|
15555
|
+
}
|
|
15556
|
+
}
|
|
15557
|
+
}, connectTimeoutMs);
|
|
15501
15558
|
ws.onopen = () => {
|
|
15559
|
+
this.clearConnectTimeout();
|
|
15502
15560
|
this.retryCount = 0;
|
|
15503
15561
|
this.lastActivity = Date.now();
|
|
15504
15562
|
logger.websocket(`connected (readyState ${ws.readyState})`);
|
|
15505
15563
|
this.onConnectionChange?.(true);
|
|
15506
|
-
onOpen?.();
|
|
15564
|
+
this.currentOptions?.onOpen?.();
|
|
15507
15565
|
this.startHeartbeat();
|
|
15508
15566
|
};
|
|
15509
15567
|
ws.onmessage = (event) => {
|
|
15510
15568
|
this.lastActivity = Date.now();
|
|
15511
|
-
onMessage?.(event.data);
|
|
15569
|
+
this.currentOptions?.onMessage?.(event.data);
|
|
15512
15570
|
};
|
|
15513
15571
|
ws.onerror = (error) => {
|
|
15514
15572
|
console.error("WebSocket error:", error);
|
|
15515
|
-
onError?.(error);
|
|
15573
|
+
this.currentOptions?.onError?.(error);
|
|
15516
15574
|
};
|
|
15517
15575
|
ws.onclose = (ev) => {
|
|
15576
|
+
this.clearConnectTimeout();
|
|
15518
15577
|
this.stopHeartbeat();
|
|
15519
15578
|
const everOpened = ev.code !== 1006 || ws.readyState === WebSocket.CLOSED;
|
|
15520
15579
|
logger.websocket(`disconnected (code ${ev.code}, clean ${ev.wasClean}, everOpened ${everOpened})`);
|
|
15521
15580
|
this.onConnectionChange?.(false);
|
|
15522
|
-
onClose?.(ev);
|
|
15581
|
+
this.currentOptions?.onClose?.(ev);
|
|
15523
15582
|
if (this.refCount > 0) this.attemptReconnect();
|
|
15524
15583
|
};
|
|
15525
15584
|
}
|
|
15585
|
+
detachHandlers(ws) {
|
|
15586
|
+
ws.onopen = null;
|
|
15587
|
+
ws.onmessage = null;
|
|
15588
|
+
ws.onerror = null;
|
|
15589
|
+
ws.onclose = null;
|
|
15590
|
+
}
|
|
15591
|
+
clearConnectTimeout() {
|
|
15592
|
+
if (this.connectTimeoutId) {
|
|
15593
|
+
clearTimeout(this.connectTimeoutId);
|
|
15594
|
+
this.connectTimeoutId = null;
|
|
15595
|
+
}
|
|
15596
|
+
}
|
|
15597
|
+
/**
|
|
15598
|
+
* after wake/offline the retry chain may be exhausted or dead — coming back online or
|
|
15599
|
+
* refocusing the tab is the moment to start over with a fresh socket
|
|
15600
|
+
*/
|
|
15601
|
+
installRecoveryListeners() {
|
|
15602
|
+
if (this.recoveryListenersInstalled || typeof window === "undefined") return;
|
|
15603
|
+
this.recoveryListenersInstalled = true;
|
|
15604
|
+
window.addEventListener("online", () => this.recover("online"));
|
|
15605
|
+
document.addEventListener("visibilitychange", () => {
|
|
15606
|
+
if (document.visibilityState === "visible") this.recover("visible");
|
|
15607
|
+
});
|
|
15608
|
+
}
|
|
15609
|
+
recover(reason) {
|
|
15610
|
+
if (this.refCount === 0 || !this.currentOptions) return;
|
|
15611
|
+
if (this.socket && (this.socket.readyState === WebSocket.OPEN || this.socket.readyState === WebSocket.CONNECTING)) return;
|
|
15612
|
+
logger.websocket(`recovery (${reason}): socket not open, reconnecting`);
|
|
15613
|
+
this.reconnect();
|
|
15614
|
+
}
|
|
15526
15615
|
startHeartbeat() {
|
|
15527
15616
|
this.stopHeartbeat();
|
|
15528
15617
|
const heartbeatIntervalMs = this.currentOptions?.heartbeatIntervalMs ?? 3e4;
|
|
@@ -15602,15 +15691,18 @@ class WebSocketManager {
|
|
|
15602
15691
|
}
|
|
15603
15692
|
_teardownSocket(reason) {
|
|
15604
15693
|
this.stopHeartbeat();
|
|
15694
|
+
this.clearConnectTimeout();
|
|
15605
15695
|
if (this.retryTimeoutId) {
|
|
15606
15696
|
clearTimeout(this.retryTimeoutId);
|
|
15607
15697
|
this.retryTimeoutId = null;
|
|
15608
15698
|
}
|
|
15609
15699
|
const ws = this.socket;
|
|
15610
15700
|
this.socket = null;
|
|
15611
|
-
if (ws
|
|
15701
|
+
if (!ws) return;
|
|
15702
|
+
this.detachHandlers(ws);
|
|
15703
|
+
if (ws.readyState === WebSocket.OPEN) {
|
|
15612
15704
|
ws.close(1e3, reason);
|
|
15613
|
-
} else if (ws
|
|
15705
|
+
} else if (ws.readyState === WebSocket.CONNECTING) {
|
|
15614
15706
|
try {
|
|
15615
15707
|
ws.close();
|
|
15616
15708
|
} catch {
|
|
@@ -15621,7 +15713,6 @@ class WebSocketManager {
|
|
|
15621
15713
|
if (this.socket && this.isConnected) {
|
|
15622
15714
|
try {
|
|
15623
15715
|
this.socket.send(JSON.stringify(message));
|
|
15624
|
-
this.lastActivity = Date.now();
|
|
15625
15716
|
return true;
|
|
15626
15717
|
} catch {
|
|
15627
15718
|
return false;
|
|
@@ -15630,32 +15721,323 @@ class WebSocketManager {
|
|
|
15630
15721
|
return false;
|
|
15631
15722
|
}
|
|
15632
15723
|
}
|
|
15724
|
+
let getTokenImpl = null;
|
|
15725
|
+
function setGetToken(fn) {
|
|
15726
|
+
getTokenImpl = fn;
|
|
15727
|
+
}
|
|
15728
|
+
async function resolveToken() {
|
|
15729
|
+
if (!getTokenImpl) return void 0;
|
|
15730
|
+
return await getTokenImpl();
|
|
15731
|
+
}
|
|
15732
|
+
const PROBE_TYPE = "session:probe";
|
|
15733
|
+
const PROBE_INTERVAL_MS = 45e3;
|
|
15734
|
+
const REAUTH_MIN_INTERVAL_MS = 2e3;
|
|
15735
|
+
const REAUTH_MAX_ATTEMPTS = 3;
|
|
15736
|
+
const REAUTH_BACKOFF_MS = 2e3;
|
|
15737
|
+
const QUEUE_MAX = 100;
|
|
15738
|
+
const PENDING_MAX = 50;
|
|
15739
|
+
const PENDING_MAX_AGE_MS = 5 * 60 * 1e3;
|
|
15740
|
+
function textMatches(sent, echoed) {
|
|
15741
|
+
if (typeof sent !== "string" || typeof echoed !== "string") return false;
|
|
15742
|
+
return sent === echoed || sent.slice(0, 1e4) === echoed;
|
|
15743
|
+
}
|
|
15744
|
+
class ChatSession {
|
|
15745
|
+
transport;
|
|
15746
|
+
options = null;
|
|
15747
|
+
state = "disconnected";
|
|
15748
|
+
everReady = false;
|
|
15749
|
+
lostSinceReady = false;
|
|
15750
|
+
reauthAttempts = 0;
|
|
15751
|
+
lastAuthSentAt = 0;
|
|
15752
|
+
reauthTimerId = null;
|
|
15753
|
+
/** backlog waiting for the session to become ready */
|
|
15754
|
+
queue = [];
|
|
15755
|
+
/** sent but not yet confirmed by a server echo */
|
|
15756
|
+
pending = [];
|
|
15757
|
+
probeIntervalId = null;
|
|
15758
|
+
constructor(transport) {
|
|
15759
|
+
this.transport = transport;
|
|
15760
|
+
}
|
|
15761
|
+
get sessionState() {
|
|
15762
|
+
return this.state;
|
|
15763
|
+
}
|
|
15764
|
+
start(options) {
|
|
15765
|
+
this.options = options;
|
|
15766
|
+
this.installProbe();
|
|
15767
|
+
this.setState("connecting");
|
|
15768
|
+
this.transport.connect({
|
|
15769
|
+
url: options.url,
|
|
15770
|
+
maxRetries: Infinity,
|
|
15771
|
+
// chat is the product — never stop trying
|
|
15772
|
+
maxRetryDelay: 3e4,
|
|
15773
|
+
onOpen: () => this.handleOpen(),
|
|
15774
|
+
onMessage: (raw) => this.handleFrame(raw),
|
|
15775
|
+
onClose: () => this.handleClose()
|
|
15776
|
+
});
|
|
15777
|
+
if (this.transport.isConnected && this.state === "connecting") this.handleOpen();
|
|
15778
|
+
}
|
|
15779
|
+
/**
|
|
15780
|
+
* Send a frame through the session. Returns false only for unqueued frames that could
|
|
15781
|
+
* not be sent right now; queued frames always succeed eventually or expire.
|
|
15782
|
+
*/
|
|
15783
|
+
send(payload, sendOptions = {}) {
|
|
15784
|
+
const entry = { payload, ...sendOptions };
|
|
15785
|
+
if (this.state === "ready" && this.transport.isConnected) return this.dispatch(entry);
|
|
15786
|
+
if (!entry.queue) return false;
|
|
15787
|
+
this.enqueue(entry);
|
|
15788
|
+
return true;
|
|
15789
|
+
}
|
|
15790
|
+
/** teardown (tests / HMR) — the socket itself is refcounted by the transport */
|
|
15791
|
+
destroy() {
|
|
15792
|
+
this.clearReauthTimer();
|
|
15793
|
+
if (this.probeIntervalId) {
|
|
15794
|
+
clearInterval(this.probeIntervalId);
|
|
15795
|
+
this.probeIntervalId = null;
|
|
15796
|
+
}
|
|
15797
|
+
if (typeof window !== "undefined") {
|
|
15798
|
+
window.removeEventListener("online", this.probeNow);
|
|
15799
|
+
document.removeEventListener("visibilitychange", this.onVisibilityChange);
|
|
15800
|
+
}
|
|
15801
|
+
this.queue = [];
|
|
15802
|
+
this.pending = [];
|
|
15803
|
+
this.setState("disconnected");
|
|
15804
|
+
}
|
|
15805
|
+
handleOpen() {
|
|
15806
|
+
this.clearReauthTimer();
|
|
15807
|
+
this.reauthAttempts = 0;
|
|
15808
|
+
this.setState("authenticating");
|
|
15809
|
+
this.authenticate();
|
|
15810
|
+
}
|
|
15811
|
+
handleClose() {
|
|
15812
|
+
this.clearReauthTimer();
|
|
15813
|
+
if (this.everReady) this.lostSinceReady = true;
|
|
15814
|
+
this.setState("connecting");
|
|
15815
|
+
}
|
|
15816
|
+
async authenticate() {
|
|
15817
|
+
this.lastAuthSentAt = Date.now();
|
|
15818
|
+
let token;
|
|
15819
|
+
try {
|
|
15820
|
+
token = await resolveToken();
|
|
15821
|
+
} catch (error) {
|
|
15822
|
+
logger.session(`token resolution failed: ${error instanceof Error ? error.message : error}`);
|
|
15823
|
+
}
|
|
15824
|
+
token ??= this.options?.fallbackToken?.();
|
|
15825
|
+
if (!token) {
|
|
15826
|
+
logger.session("no auth token available; retrying");
|
|
15827
|
+
this.scheduleReauth(REAUTH_BACKOFF_MS);
|
|
15828
|
+
return;
|
|
15829
|
+
}
|
|
15830
|
+
if (!this.transport.send({ type: "authenticate", token })) return;
|
|
15831
|
+
this.setReady();
|
|
15832
|
+
}
|
|
15833
|
+
setReady() {
|
|
15834
|
+
const restored = this.everReady && this.lostSinceReady;
|
|
15835
|
+
this.everReady = true;
|
|
15836
|
+
this.lostSinceReady = false;
|
|
15837
|
+
this.setState("ready");
|
|
15838
|
+
if (restored) {
|
|
15839
|
+
this.requeuePending();
|
|
15840
|
+
this.options?.onSessionRestored?.();
|
|
15841
|
+
}
|
|
15842
|
+
this.flushQueue();
|
|
15843
|
+
}
|
|
15844
|
+
setState(next) {
|
|
15845
|
+
if (this.state === next) return;
|
|
15846
|
+
this.state = next;
|
|
15847
|
+
logger.session(`state → ${next}`);
|
|
15848
|
+
this.options?.onStateChange?.(next);
|
|
15849
|
+
}
|
|
15850
|
+
handleFrame(raw) {
|
|
15851
|
+
let frame;
|
|
15852
|
+
try {
|
|
15853
|
+
frame = JSON.parse(raw);
|
|
15854
|
+
} catch {
|
|
15855
|
+
logger.session("unparseable frame received; ignored");
|
|
15856
|
+
return;
|
|
15857
|
+
}
|
|
15858
|
+
if (!frame || typeof frame.type !== "string") return;
|
|
15859
|
+
if (frame.type === "pong" || frame.type === "welcome") return;
|
|
15860
|
+
if (frame.type === "authenticated") {
|
|
15861
|
+
this.reauthAttempts = 0;
|
|
15862
|
+
if (this.state !== "ready") this.setReady();
|
|
15863
|
+
return;
|
|
15864
|
+
}
|
|
15865
|
+
if (frame.type === "session:alive") {
|
|
15866
|
+
this.reauthAttempts = 0;
|
|
15867
|
+
return;
|
|
15868
|
+
}
|
|
15869
|
+
if (frame.type === "error") {
|
|
15870
|
+
this.handleError(frame);
|
|
15871
|
+
return;
|
|
15872
|
+
}
|
|
15873
|
+
this.reauthAttempts = 0;
|
|
15874
|
+
this.confirmEcho(frame);
|
|
15875
|
+
try {
|
|
15876
|
+
this.options?.onMessage?.(frame);
|
|
15877
|
+
} catch (error) {
|
|
15878
|
+
logger.session(`message handler failed: ${error instanceof Error ? error.message : error}`);
|
|
15879
|
+
}
|
|
15880
|
+
}
|
|
15881
|
+
handleError(frame) {
|
|
15882
|
+
const error = String(frame.error ?? "");
|
|
15883
|
+
const messageType = typeof frame.messageType === "string" ? frame.messageType : void 0;
|
|
15884
|
+
if (error === "UNKNOWN_CLIENT") {
|
|
15885
|
+
this.handleSessionLost(messageType ?? "unknown");
|
|
15886
|
+
return;
|
|
15887
|
+
}
|
|
15888
|
+
if (error === "AUTH_FAILED") {
|
|
15889
|
+
this.handleAuthFailed();
|
|
15890
|
+
return;
|
|
15891
|
+
}
|
|
15892
|
+
if (messageType === PROBE_TYPE) {
|
|
15893
|
+
this.reauthAttempts = 0;
|
|
15894
|
+
return;
|
|
15895
|
+
}
|
|
15896
|
+
if (messageType) this.settleRejected(messageType);
|
|
15897
|
+
logger.session(`server error ${error}${messageType ? ` (${messageType})` : ""}`);
|
|
15898
|
+
this.options?.onMessage?.(frame);
|
|
15899
|
+
}
|
|
15900
|
+
handleSessionLost(context) {
|
|
15901
|
+
this.lostSinceReady = true;
|
|
15902
|
+
if (this.state === "ready") this.setState("authenticating");
|
|
15903
|
+
if (this.state !== "authenticating") return;
|
|
15904
|
+
if (this.reauthAttempts >= REAUTH_MAX_ATTEMPTS) {
|
|
15905
|
+
logger.session("re-authentication keeps failing; forcing reconnect");
|
|
15906
|
+
this.hardReconnect();
|
|
15907
|
+
return;
|
|
15908
|
+
}
|
|
15909
|
+
logger.session(`session lost (${context}); re-authenticating`);
|
|
15910
|
+
this.reauthAttempts++;
|
|
15911
|
+
const wait = REAUTH_MIN_INTERVAL_MS - (Date.now() - this.lastAuthSentAt);
|
|
15912
|
+
if (wait > 0) this.scheduleReauth(wait);
|
|
15913
|
+
else this.authenticate();
|
|
15914
|
+
}
|
|
15915
|
+
handleAuthFailed() {
|
|
15916
|
+
this.lostSinceReady = true;
|
|
15917
|
+
if (this.state === "ready") this.setState("authenticating");
|
|
15918
|
+
this.reauthAttempts++;
|
|
15919
|
+
if (this.reauthAttempts > REAUTH_MAX_ATTEMPTS) {
|
|
15920
|
+
logger.session("authentication failing repeatedly; forcing reconnect");
|
|
15921
|
+
this.hardReconnect();
|
|
15922
|
+
return;
|
|
15923
|
+
}
|
|
15924
|
+
logger.session(`authentication failed (attempt ${this.reauthAttempts}); retrying with a fresh token`);
|
|
15925
|
+
this.scheduleReauth(REAUTH_BACKOFF_MS * this.reauthAttempts);
|
|
15926
|
+
}
|
|
15927
|
+
hardReconnect() {
|
|
15928
|
+
this.clearReauthTimer();
|
|
15929
|
+
this.reauthAttempts = 0;
|
|
15930
|
+
this.setState("connecting");
|
|
15931
|
+
this.transport.reconnect();
|
|
15932
|
+
}
|
|
15933
|
+
scheduleReauth(delayMs) {
|
|
15934
|
+
if (this.reauthTimerId) return;
|
|
15935
|
+
this.reauthTimerId = setTimeout(() => {
|
|
15936
|
+
this.reauthTimerId = null;
|
|
15937
|
+
if (this.state === "authenticating" && this.transport.isConnected) this.authenticate();
|
|
15938
|
+
}, delayMs);
|
|
15939
|
+
}
|
|
15940
|
+
clearReauthTimer() {
|
|
15941
|
+
if (this.reauthTimerId) {
|
|
15942
|
+
clearTimeout(this.reauthTimerId);
|
|
15943
|
+
this.reauthTimerId = null;
|
|
15944
|
+
}
|
|
15945
|
+
}
|
|
15946
|
+
/** server echoes settle tracked sends: own message echo / conversation:new with our client id */
|
|
15947
|
+
confirmEcho(frame) {
|
|
15948
|
+
if (frame.type === "message") {
|
|
15949
|
+
const ownUser = this.options?.ownUserId?.();
|
|
15950
|
+
if (!ownUser || frame.user !== ownUser) return;
|
|
15951
|
+
const index = this.pending.findIndex((entry) => entry.payload.type === "message:add" && entry.payload.conversation === frame.conversation && textMatches(entry.payload.message, frame.message));
|
|
15952
|
+
if (index !== -1) this.pending.splice(index, 1);
|
|
15953
|
+
return;
|
|
15954
|
+
}
|
|
15955
|
+
if (frame.type === "conversation:new" && frame.id) {
|
|
15956
|
+
const index = this.pending.findIndex((entry) => entry.payload.type === "conversation:start" && entry.payload.id === frame.id);
|
|
15957
|
+
if (index !== -1) this.pending.splice(index, 1);
|
|
15958
|
+
}
|
|
15959
|
+
}
|
|
15960
|
+
settleRejected(messageType) {
|
|
15961
|
+
const index = this.pending.findIndex((entry) => entry.payload.type === messageType);
|
|
15962
|
+
if (index !== -1) this.pending.splice(index, 1);
|
|
15963
|
+
}
|
|
15964
|
+
dispatch(entry) {
|
|
15965
|
+
if (!this.transport.send(entry.payload)) {
|
|
15966
|
+
if (entry.queue) this.queue.unshift(entry);
|
|
15967
|
+
return false;
|
|
15968
|
+
}
|
|
15969
|
+
if (entry.track) {
|
|
15970
|
+
this.pending.push({ ...entry, sentAt: Date.now() });
|
|
15971
|
+
if (this.pending.length > PENDING_MAX) this.pending.splice(0, this.pending.length - PENDING_MAX);
|
|
15972
|
+
}
|
|
15973
|
+
return true;
|
|
15974
|
+
}
|
|
15975
|
+
enqueue(entry) {
|
|
15976
|
+
if (entry.replaceKey) this.queue = this.queue.filter((queued) => queued.replaceKey !== entry.replaceKey);
|
|
15977
|
+
this.queue.push(entry);
|
|
15978
|
+
if (this.queue.length > QUEUE_MAX) {
|
|
15979
|
+
this.queue.splice(0, this.queue.length - QUEUE_MAX);
|
|
15980
|
+
logger.session("outbound queue overflow; oldest entries dropped");
|
|
15981
|
+
}
|
|
15982
|
+
}
|
|
15983
|
+
/** unconfirmed sends from before the loss go to the front of the backlog for resend */
|
|
15984
|
+
requeuePending() {
|
|
15985
|
+
if (!this.pending.length) return;
|
|
15986
|
+
const now = Date.now();
|
|
15987
|
+
const fresh = this.pending.filter((entry) => now - (entry.sentAt ?? now) < PENDING_MAX_AGE_MS);
|
|
15988
|
+
const dropped = this.pending.length - fresh.length;
|
|
15989
|
+
if (dropped) logger.session(`${dropped} unconfirmed frame(s) too old to resend; dropped`);
|
|
15990
|
+
this.pending = [];
|
|
15991
|
+
this.queue = [...fresh, ...this.queue];
|
|
15992
|
+
}
|
|
15993
|
+
flushQueue() {
|
|
15994
|
+
if (this.state !== "ready" || !this.queue.length) return;
|
|
15995
|
+
const backlog = this.queue;
|
|
15996
|
+
this.queue = [];
|
|
15997
|
+
logger.session(`flushing ${backlog.length} queued frame(s)`);
|
|
15998
|
+
for (let index = 0; index < backlog.length; index++) {
|
|
15999
|
+
if (!this.dispatch(backlog[index])) {
|
|
16000
|
+
this.queue.push(...backlog.slice(index + 1).filter((rest) => rest.queue));
|
|
16001
|
+
return;
|
|
16002
|
+
}
|
|
16003
|
+
}
|
|
16004
|
+
}
|
|
16005
|
+
installProbe() {
|
|
16006
|
+
if (this.probeIntervalId || typeof window === "undefined") return;
|
|
16007
|
+
this.probeIntervalId = setInterval(() => this.probe(), PROBE_INTERVAL_MS);
|
|
16008
|
+
window.addEventListener("online", this.probeNow);
|
|
16009
|
+
document.addEventListener("visibilitychange", this.onVisibilityChange);
|
|
16010
|
+
}
|
|
16011
|
+
probeNow = () => this.probe();
|
|
16012
|
+
onVisibilityChange = () => {
|
|
16013
|
+
if (document.visibilityState === "visible") this.probe();
|
|
16014
|
+
};
|
|
16015
|
+
/**
|
|
16016
|
+
* the registry entry can die without any local traffic (eviction, server cleanup) and
|
|
16017
|
+
* an idle client would never notice — it just stops receiving messages. the periodic
|
|
16018
|
+
* probe forces the server to reveal a dead session via UNKNOWN_CLIENT.
|
|
16019
|
+
*/
|
|
16020
|
+
probe() {
|
|
16021
|
+
if (this.state !== "ready" || !this.transport.isConnected) return;
|
|
16022
|
+
if (typeof document !== "undefined" && document.visibilityState !== "visible") return;
|
|
16023
|
+
this.transport.send({ type: PROBE_TYPE });
|
|
16024
|
+
}
|
|
16025
|
+
}
|
|
16026
|
+
const chatSession = new ChatSession(WebSocketManager.getInstance());
|
|
15633
16027
|
function useWebSocket() {
|
|
15634
16028
|
const wsManager = WebSocketManager.getInstance();
|
|
15635
|
-
const mainStore = useMainStore();
|
|
15636
16029
|
wsManager.acquire();
|
|
15637
|
-
|
|
15638
|
-
|
|
15639
|
-
};
|
|
15640
|
-
const
|
|
15641
|
-
const disconnect = () => wsManager.disconnect();
|
|
15642
|
-
const reconnect = () => wsManager.reconnect();
|
|
15643
|
-
const conversationStart = (message, participants, name, id, operationMode) => wsManager.send({ type: "conversation:start", message, participants, name, id, operationMode });
|
|
15644
|
-
const conversationLastRead = (conversation, lastReadId) => wsManager.send({ type: "conversation:lastRead", conversation, lastReadId });
|
|
15645
|
-
const messageAdd = (message, conversation) => wsManager.send({ type: "message:add", message, conversation });
|
|
15646
|
-
const authenticate = (token) => wsManager.send({ type: "authenticate", token });
|
|
15647
|
-
const conversationTyping = (conversation, typing) => wsManager.send({ type: "conversation:typing", conversation, typing });
|
|
16030
|
+
const conversationStart = (message, participants, name, id, operationMode) => chatSession.send({ type: "conversation:start", message, participants, name, id, operationMode }, { queue: true, track: true });
|
|
16031
|
+
const conversationLastRead = (conversation, lastReadId) => chatSession.send({ type: "conversation:lastRead", conversation, lastReadId }, { queue: true, replaceKey: `lastRead:${conversation}` });
|
|
16032
|
+
const messageAdd = (message, conversation) => chatSession.send({ type: "message:add", message, conversation }, { queue: true, track: true });
|
|
16033
|
+
const conversationTyping = (conversation, typing) => chatSession.send({ type: "conversation:typing", conversation, typing });
|
|
15648
16034
|
onUnmounted(() => {
|
|
15649
16035
|
wsManager.release();
|
|
15650
16036
|
});
|
|
15651
16037
|
return {
|
|
15652
|
-
connect,
|
|
15653
|
-
disconnect,
|
|
15654
|
-
reconnect,
|
|
15655
16038
|
conversationStart,
|
|
15656
16039
|
conversationLastRead,
|
|
15657
16040
|
messageAdd,
|
|
15658
|
-
authenticate,
|
|
15659
16041
|
conversationTyping
|
|
15660
16042
|
};
|
|
15661
16043
|
}
|
|
@@ -15729,14 +16111,6 @@ function handleMessages(message) {
|
|
|
15729
16111
|
}
|
|
15730
16112
|
function setGetUsers(fn) {
|
|
15731
16113
|
}
|
|
15732
|
-
let getTokenImpl = null;
|
|
15733
|
-
function setGetToken(fn) {
|
|
15734
|
-
getTokenImpl = fn;
|
|
15735
|
-
}
|
|
15736
|
-
async function resolveToken() {
|
|
15737
|
-
if (!getTokenImpl) return void 0;
|
|
15738
|
-
return await getTokenImpl();
|
|
15739
|
-
}
|
|
15740
16114
|
function getName(name, type, namespace) {
|
|
15741
16115
|
return `${name}-${type}`;
|
|
15742
16116
|
}
|
|
@@ -16056,8 +16430,37 @@ function groupMessages(messages, user) {
|
|
|
16056
16430
|
});
|
|
16057
16431
|
return Object.values(dateGroups);
|
|
16058
16432
|
}
|
|
16433
|
+
function useChatVisibility(element) {
|
|
16434
|
+
const mainStore = useMainStore();
|
|
16435
|
+
const elementVisible = /* @__PURE__ */ ref(false);
|
|
16436
|
+
const documentVisible = /* @__PURE__ */ ref(typeof document === "undefined" || document.visibilityState === "visible");
|
|
16437
|
+
const overlayed = computed(() => mainStore.viewMode === "compact" && !!mainStore.leftTarget);
|
|
16438
|
+
const chatVisible = computed(() => elementVisible.value && documentVisible.value && !overlayed.value);
|
|
16439
|
+
let observer;
|
|
16440
|
+
function onVisibilityChange() {
|
|
16441
|
+
documentVisible.value = document.visibilityState === "visible";
|
|
16442
|
+
}
|
|
16443
|
+
if (typeof document !== "undefined") document.addEventListener("visibilitychange", onVisibilityChange);
|
|
16444
|
+
watch(element, (target) => {
|
|
16445
|
+
observer?.disconnect();
|
|
16446
|
+
observer = void 0;
|
|
16447
|
+
if (!target || typeof IntersectionObserver === "undefined") {
|
|
16448
|
+
elementVisible.value = !!target;
|
|
16449
|
+
return;
|
|
16450
|
+
}
|
|
16451
|
+
observer = new IntersectionObserver(([entry]) => {
|
|
16452
|
+
elementVisible.value = entry.isIntersecting;
|
|
16453
|
+
});
|
|
16454
|
+
observer.observe(target);
|
|
16455
|
+
}, { immediate: true });
|
|
16456
|
+
onBeforeUnmount(() => {
|
|
16457
|
+
observer?.disconnect();
|
|
16458
|
+
if (typeof document !== "undefined") document.removeEventListener("visibilitychange", onVisibilityChange);
|
|
16459
|
+
});
|
|
16460
|
+
return { chatVisible };
|
|
16461
|
+
}
|
|
16059
16462
|
const _hoisted_1$d = { class: "chat-messages" };
|
|
16060
|
-
const _hoisted_2$
|
|
16463
|
+
const _hoisted_2$a = { class: "date-separator" };
|
|
16061
16464
|
const _hoisted_3$5 = { class: "message-content" };
|
|
16062
16465
|
const _hoisted_4$2 = ["id"];
|
|
16063
16466
|
const _hoisted_5$2 = {
|
|
@@ -16066,7 +16469,7 @@ const _hoisted_5$2 = {
|
|
|
16066
16469
|
};
|
|
16067
16470
|
const SCROLL_DEBOUNCE_MS = 100;
|
|
16068
16471
|
const SCROLL_EDGE_PERCENT = 10;
|
|
16069
|
-
const _sfc_main$
|
|
16472
|
+
const _sfc_main$i = /* @__PURE__ */ defineComponent({
|
|
16070
16473
|
__name: "chat.module",
|
|
16071
16474
|
props: {
|
|
16072
16475
|
_id: { type: String },
|
|
@@ -16093,6 +16496,7 @@ const _sfc_main$h = /* @__PURE__ */ defineComponent({
|
|
|
16093
16496
|
const newChatExists = /* @__PURE__ */ ref(false);
|
|
16094
16497
|
const existingChat = /* @__PURE__ */ ref(null);
|
|
16095
16498
|
const mainStore = useMainStore();
|
|
16499
|
+
const { chatVisible } = useChatVisibility(chatMessagesRef);
|
|
16096
16500
|
let scrollDebounceTimer = null;
|
|
16097
16501
|
let typingIdleTimer = null;
|
|
16098
16502
|
let lastTypingSent = 0;
|
|
@@ -16163,12 +16567,16 @@ const _sfc_main$h = /* @__PURE__ */ defineComponent({
|
|
|
16163
16567
|
}
|
|
16164
16568
|
}
|
|
16165
16569
|
function updateLastRead() {
|
|
16570
|
+
if (!chatVisible.value) return;
|
|
16166
16571
|
if (conversation.value?.participant?.lastReadId < conversation.value?.lastMessage?.id) {
|
|
16167
16572
|
conversationLastRead(props._id, conversation.value.lastMessage.id);
|
|
16168
16573
|
conversationsStore.setLastReadId(props._id, conversation.value.lastMessage.id);
|
|
16169
16574
|
conversationsStore.updateUnread(props._id);
|
|
16170
16575
|
}
|
|
16171
16576
|
}
|
|
16577
|
+
watch(chatVisible, (visible) => {
|
|
16578
|
+
if (visible) updateLastRead();
|
|
16579
|
+
});
|
|
16172
16580
|
function scrollToBottom() {
|
|
16173
16581
|
if (chatMessagesRef.value) {
|
|
16174
16582
|
chatMessagesRef.value.scrollTop = chatMessagesRef.value.scrollHeight;
|
|
@@ -16301,7 +16709,7 @@ const _sfc_main$h = /* @__PURE__ */ defineComponent({
|
|
|
16301
16709
|
key: dateGroup.date,
|
|
16302
16710
|
class: "messages-group"
|
|
16303
16711
|
}, [
|
|
16304
|
-
createBaseVNode("div", _hoisted_2$
|
|
16712
|
+
createBaseVNode("div", _hoisted_2$a, toDisplayString$1(dateGroup.date), 1),
|
|
16305
16713
|
(openBlock(true), createElementBlock(Fragment, null, renderList(dateGroup.userTimeGroups, (group, index) => {
|
|
16306
16714
|
return openBlock(), createElementBlock("div", {
|
|
16307
16715
|
key: index,
|
|
@@ -16350,8 +16758,8 @@ const _sfc_main$h = /* @__PURE__ */ defineComponent({
|
|
|
16350
16758
|
};
|
|
16351
16759
|
}
|
|
16352
16760
|
});
|
|
16353
|
-
const _style_0$
|
|
16354
|
-
const ChatModule = /* @__PURE__ */ _export_sfc(_sfc_main$
|
|
16761
|
+
const _style_0$f = ".chat-module[data-v-6c9f82e3]{display:grid;height:100%;grid-template-rows:max-content 1fr max-content;overflow:hidden}.chat-module.isNew[data-v-6c9f82e3]{grid-template-rows:max-content 1fr max-content}.chat-module .notice-partial[data-v-6c9f82e3]{position:absolute;align-self:center;justify-self:center;z-index:100}.chat-module .chat-messages-scroll-container[data-v-6c9f82e3]{overflow-y:auto;position:relative;padding-bottom:50px;display:grid}.chat-module .chat-messages-scroll-container .chat-messages[data-v-6c9f82e3]{display:grid;grid-auto-rows:max-content;align-content:end}.chat-module .chat-messages-scroll-container .chat-messages .messages-group[data-v-6c9f82e3]{display:grid;gap:20px;margin:0 20px;grid-auto-rows:max-content;align-content:end}.chat-module .chat-messages-scroll-container .chat-messages .messages-group .message[data-v-6c9f82e3]{display:grid;grid-template-rows:auto auto;gap:10px;justify-self:start}.chat-module .chat-messages-scroll-container .chat-messages .messages-group .message.system[data-v-6c9f82e3]{width:100%;text-align:center;align-content:center;justify-content:center}.chat-module .chat-messages-scroll-container .chat-messages .messages-group .message.system header[data-v-6c9f82e3]{justify-content:center;grid-template-columns:1fr}.chat-module .chat-messages-scroll-container .chat-messages .messages-group .message.system header time[data-v-6c9f82e3]{text-align:center;color:var(--scm-color-muted);font-size:.75em}.chat-module .chat-messages-scroll-container .chat-messages .messages-group .message.system .message-content p[data-v-6c9f82e3]{background-color:transparent;padding:0;color:var(--scm-color-muted);font-size:.75em;white-space:pre-wrap}.chat-module .chat-messages-scroll-container .chat-messages .messages-group .message header[data-v-6c9f82e3]{display:grid;grid-template-columns:max-content max-content;gap:10px;width:100%;font-size:.875em}.chat-module .chat-messages-scroll-container .chat-messages .messages-group .message header time[data-v-6c9f82e3]{text-align:right}.chat-module .chat-messages-scroll-container .chat-messages .messages-group .message .message-content[data-v-6c9f82e3]{display:grid;gap:4px}.chat-module .chat-messages-scroll-container .chat-messages .messages-group .message .message-content p[data-v-6c9f82e3]{padding:10px;border-radius:5px;background-color:var(--scm-color-primary);color:#fff;justify-self:start;white-space:pre-wrap;font-size:1em}.chat-module .chat-messages-scroll-container .chat-messages .messages-group .message.isUser[data-v-6c9f82e3]{justify-self:end}.chat-module .chat-messages-scroll-container .chat-messages .messages-group .message.isUser p[data-v-6c9f82e3]{justify-self:end;background-color:var(--scm-color-own);color:#fff}.chat-module .chat-messages-scroll-container .chat-messages .messages-group .message.isUser header[data-v-6c9f82e3]{grid-template-columns:1fr}.chat-module .typing-indicator[data-v-6c9f82e3]{padding:4px 20px;font-size:.75em;color:var(--scm-color-muted);font-style:italic}.chat-module .date-separator[data-v-6c9f82e3]{text-align:center;padding:20px 0;font-size:.875em;font-weight:700}";
|
|
16762
|
+
const ChatModule = /* @__PURE__ */ _export_sfc(_sfc_main$i, [["styles", [_style_0$f]], ["__scopeId", "data-v-6c9f82e3"]]);
|
|
16355
16763
|
function sdkOptions() {
|
|
16356
16764
|
const mainStore = useMainStore();
|
|
16357
16765
|
return {
|
|
@@ -16380,7 +16788,7 @@ const useContactsStore = /* @__PURE__ */ defineStore("contacts", () => {
|
|
|
16380
16788
|
};
|
|
16381
16789
|
});
|
|
16382
16790
|
const _hoisted_1$c = { class: "contacts-module" };
|
|
16383
|
-
const _hoisted_2$
|
|
16791
|
+
const _hoisted_2$9 = {
|
|
16384
16792
|
key: 0,
|
|
16385
16793
|
class: "controls"
|
|
16386
16794
|
};
|
|
@@ -16396,7 +16804,7 @@ const _hoisted_8$1 = {
|
|
|
16396
16804
|
key: 0,
|
|
16397
16805
|
class: "selected-indicator"
|
|
16398
16806
|
};
|
|
16399
|
-
const _sfc_main$
|
|
16807
|
+
const _sfc_main$h = /* @__PURE__ */ defineComponent({
|
|
16400
16808
|
__name: "contacts.module",
|
|
16401
16809
|
setup(__props) {
|
|
16402
16810
|
const mainStore = useMainStore();
|
|
@@ -16499,7 +16907,7 @@ const _sfc_main$g = /* @__PURE__ */ defineComponent({
|
|
|
16499
16907
|
const _component_button_partial = resolveComponent("button-partial");
|
|
16500
16908
|
const _component_user_avatar_partial = resolveComponent("user-avatar-partial");
|
|
16501
16909
|
return openBlock(), createElementBlock("article", _hoisted_1$c, [
|
|
16502
|
-
isEdit.value ? (openBlock(), createElementBlock("section", _hoisted_2$
|
|
16910
|
+
isEdit.value ? (openBlock(), createElementBlock("section", _hoisted_2$9, [
|
|
16503
16911
|
createVNode(_component_button_partial, {
|
|
16504
16912
|
variant: "primary",
|
|
16505
16913
|
size: "sm",
|
|
@@ -16587,15 +16995,31 @@ const _sfc_main$g = /* @__PURE__ */ defineComponent({
|
|
|
16587
16995
|
};
|
|
16588
16996
|
}
|
|
16589
16997
|
});
|
|
16590
|
-
const _style_0$
|
|
16591
|
-
const ContactsModule = /* @__PURE__ */ _export_sfc(_sfc_main$
|
|
16592
|
-
const
|
|
16998
|
+
const _style_0$e = ".contacts-module[data-v-045be51e]{height:100%;overflow:scroll}.contacts-module .controls[data-v-045be51e]{display:grid;grid-template-columns:1fr 1fr}.contacts-module .rights-panel[data-v-045be51e]{padding:10px 20px;border-bottom:1px solid var(--scm-color-surface)}.contacts-module .rights-panel h4[data-v-045be51e]{margin-bottom:10px}.contacts-module .rights-panel .participant-rights[data-v-045be51e]{display:grid;gap:5px;padding:10px 0}.contacts-module .rights-panel .participant-rights .rights[data-v-045be51e]{display:flex;flex-wrap:wrap;gap:10px}.contacts-module .rights-panel .participant-rights .rights .right-toggle[data-v-045be51e]{cursor:pointer;font-size:.8125em}.contacts-module .rights-panel .participant-rights .who em[data-v-045be51e]{color:var(--scm-color-muted)}.contacts-module .single-contact[data-v-045be51e]{padding:20px;cursor:pointer;display:flex;justify-content:space-between;align-items:center}.contacts-module .single-contact[data-v-045be51e]:hover{background-color:var(--scm-color-surface)}.contacts-module .single-contact.selected[data-v-045be51e]{background-color:color-mix(in srgb,var(--scm-color-primary) 15%,transparent)}.contacts-module .single-contact .selected-indicator[data-v-045be51e]{color:var(--scm-color-primary);font-weight:700}";
|
|
16999
|
+
const ContactsModule = /* @__PURE__ */ _export_sfc(_sfc_main$h, [["styles", [_style_0$e]], ["__scopeId", "data-v-045be51e"]]);
|
|
17000
|
+
const _sfc_main$g = /* @__PURE__ */ defineComponent({
|
|
17001
|
+
__name: "user-name.partial",
|
|
17002
|
+
props: {
|
|
17003
|
+
userId: { type: String }
|
|
17004
|
+
},
|
|
17005
|
+
setup(__props) {
|
|
17006
|
+
const props = __props;
|
|
17007
|
+
const usersCache = useUsersCacheStore();
|
|
17008
|
+
onMounted(() => {
|
|
17009
|
+
usersCache.ensure([props.userId]);
|
|
17010
|
+
});
|
|
17011
|
+
return (_ctx, _cache) => {
|
|
17012
|
+
return toDisplayString$1(unref(usersCache).name(props.userId));
|
|
17013
|
+
};
|
|
17014
|
+
}
|
|
17015
|
+
});
|
|
16593
17016
|
const _sfc_main$f = /* @__PURE__ */ defineComponent({
|
|
16594
17017
|
__name: "participants.partial",
|
|
16595
17018
|
props: {
|
|
16596
17019
|
participants: { type: Array },
|
|
16597
17020
|
removeUser: { type: Boolean },
|
|
16598
|
-
isNew: { type: Boolean }
|
|
17021
|
+
isNew: { type: Boolean },
|
|
17022
|
+
inline: { type: Boolean }
|
|
16599
17023
|
},
|
|
16600
17024
|
setup(__props) {
|
|
16601
17025
|
const userStore = useUserStore();
|
|
@@ -16608,29 +17032,35 @@ const _sfc_main$f = /* @__PURE__ */ defineComponent({
|
|
|
16608
17032
|
});
|
|
16609
17033
|
return (_ctx, _cache) => {
|
|
16610
17034
|
const _component_user_avatar_partial = resolveComponent("user-avatar-partial");
|
|
16611
|
-
return openBlock(), createElementBlock("section",
|
|
17035
|
+
return openBlock(), createElementBlock("section", {
|
|
17036
|
+
class: normalizeClass(["participants-partial", { "participants-partial--inline": __props.inline }])
|
|
17037
|
+
}, [
|
|
16612
17038
|
__props.isNew && !filteredParticipants.value.length ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [
|
|
16613
17039
|
createTextVNode(toDisplayString$1(_ctx.$t("select contacts")), 1)
|
|
16614
17040
|
], 64)) : (openBlock(true), createElementBlock(Fragment, { key: 1 }, renderList(filteredParticipants.value, (participant, index) => {
|
|
16615
17041
|
return openBlock(), createElementBlock(Fragment, {
|
|
16616
17042
|
key: unref(participantId)(participant)
|
|
16617
17043
|
}, [
|
|
16618
|
-
|
|
17044
|
+
__props.inline ? (openBlock(), createBlock(_sfc_main$g, {
|
|
17045
|
+
key: 0,
|
|
16619
17046
|
"user-id": unref(participantId)(participant)
|
|
16620
|
-
}, null, 8, ["user-id"]),
|
|
16621
|
-
|
|
17047
|
+
}, null, 8, ["user-id"])) : (openBlock(), createBlock(_component_user_avatar_partial, {
|
|
17048
|
+
key: 1,
|
|
17049
|
+
"user-id": unref(participantId)(participant)
|
|
17050
|
+
}, null, 8, ["user-id"])),
|
|
17051
|
+
index < filteredParticipants.value.length - 1 ? (openBlock(), createElementBlock(Fragment, { key: 2 }, [
|
|
16622
17052
|
createTextVNode(toDisplayString$1(", "))
|
|
16623
17053
|
], 64)) : createCommentVNode("", true)
|
|
16624
17054
|
], 64);
|
|
16625
17055
|
}), 128))
|
|
16626
|
-
]);
|
|
17056
|
+
], 2);
|
|
16627
17057
|
};
|
|
16628
17058
|
}
|
|
16629
17059
|
});
|
|
16630
|
-
const _style_0$
|
|
16631
|
-
const ParticipantsPartial = /* @__PURE__ */ _export_sfc(_sfc_main$f, [["styles", [_style_0$
|
|
16632
|
-
const _hoisted_1$
|
|
16633
|
-
const _hoisted_2$
|
|
17060
|
+
const _style_0$d = ".participants-partial--inline[data-v-ee2866aa]{font-size:inherit}";
|
|
17061
|
+
const ParticipantsPartial = /* @__PURE__ */ _export_sfc(_sfc_main$f, [["styles", [_style_0$d]], ["__scopeId", "data-v-ee2866aa"]]);
|
|
17062
|
+
const _hoisted_1$b = { class: "actions" };
|
|
17063
|
+
const _hoisted_2$8 = { class: "left" };
|
|
16634
17064
|
const _hoisted_3$3 = { class: "right" };
|
|
16635
17065
|
const _sfc_main$e = /* @__PURE__ */ defineComponent({
|
|
16636
17066
|
__name: "actions.partial",
|
|
@@ -16639,17 +17069,11 @@ const _sfc_main$e = /* @__PURE__ */ defineComponent({
|
|
|
16639
17069
|
const conversationsStore = useConversationsStore();
|
|
16640
17070
|
const userStore = useUserStore();
|
|
16641
17071
|
const hasChat = computed(() => mainStore.hasChat);
|
|
16642
|
-
const showConversationsButton = computed(
|
|
16643
|
-
() => hasChat.value || conversationsStore.conversations.length > 1
|
|
16644
|
-
);
|
|
16645
17072
|
const createConversation = () => {
|
|
16646
17073
|
const tempId = conversationsStore.createNew([userStore.user], userStore.user);
|
|
16647
17074
|
conversationsStore.activateConversation(tempId);
|
|
16648
|
-
mainStore.
|
|
17075
|
+
mainStore.hideLeft();
|
|
16649
17076
|
};
|
|
16650
|
-
function showConversations() {
|
|
16651
|
-
mainStore.showConversations();
|
|
16652
|
-
}
|
|
16653
17077
|
function close() {
|
|
16654
17078
|
if (mainStore.leftTarget === "contacts-edit" || mainStore.leftTarget === "contacts-new") {
|
|
16655
17079
|
mainStore.showConversations();
|
|
@@ -16658,18 +17082,13 @@ const _sfc_main$e = /* @__PURE__ */ defineComponent({
|
|
|
16658
17082
|
mainStore.closeCallback?.();
|
|
16659
17083
|
}
|
|
16660
17084
|
return (_ctx, _cache) => {
|
|
17085
|
+
const _component_conversations_button_partial = resolveComponent("conversations-button-partial");
|
|
16661
17086
|
const _component_button_partial = resolveComponent("button-partial");
|
|
16662
|
-
return openBlock(), createElementBlock("section", _hoisted_1$
|
|
16663
|
-
createBaseVNode("section", _hoisted_2$
|
|
16664
|
-
|
|
16665
|
-
key: 0,
|
|
16666
|
-
icon: "chat",
|
|
16667
|
-
variant: "secondary",
|
|
16668
|
-
"aria-label": "Conversations",
|
|
16669
|
-
onClick: showConversations
|
|
16670
|
-
})) : createCommentVNode("", true),
|
|
17087
|
+
return openBlock(), createElementBlock("section", _hoisted_1$b, [
|
|
17088
|
+
createBaseVNode("section", _hoisted_2$8, [
|
|
17089
|
+
createVNode(_component_conversations_button_partial),
|
|
16671
17090
|
hasChat.value ? (openBlock(), createBlock(_component_button_partial, {
|
|
16672
|
-
key:
|
|
17091
|
+
key: 0,
|
|
16673
17092
|
icon: "add",
|
|
16674
17093
|
"aria-label": "New chat",
|
|
16675
17094
|
onClick: createConversation
|
|
@@ -16686,10 +17105,10 @@ const _sfc_main$e = /* @__PURE__ */ defineComponent({
|
|
|
16686
17105
|
};
|
|
16687
17106
|
}
|
|
16688
17107
|
});
|
|
16689
|
-
const _style_0$
|
|
16690
|
-
const ActionsPartial = /* @__PURE__ */ _export_sfc(_sfc_main$e, [["styles", [_style_0$
|
|
16691
|
-
const _hoisted_1$
|
|
16692
|
-
const _hoisted_2$
|
|
17108
|
+
const _style_0$c = ".actions[data-v-e7780b44]{display:grid;grid-template-columns:max-content 1fr max-content;width:100%;grid-column:1/3}.actions .left[data-v-e7780b44]{grid-column:1/2;display:flex}.actions .right[data-v-e7780b44]{grid-column:3/4}";
|
|
17109
|
+
const ActionsPartial = /* @__PURE__ */ _export_sfc(_sfc_main$e, [["styles", [_style_0$c]], ["__scopeId", "data-v-e7780b44"]]);
|
|
17110
|
+
const _hoisted_1$a = { class: "background-container" };
|
|
17111
|
+
const _hoisted_2$7 = { key: 0 };
|
|
16693
17112
|
const _sfc_main$d = /* @__PURE__ */ defineComponent({
|
|
16694
17113
|
__name: "chat-header.partial",
|
|
16695
17114
|
props: {
|
|
@@ -16760,7 +17179,7 @@ const _sfc_main$d = /* @__PURE__ */ defineComponent({
|
|
|
16760
17179
|
return openBlock(), createElementBlock("header", {
|
|
16761
17180
|
class: normalizeClass(["chat-header", { isSupport: isSupport.value }])
|
|
16762
17181
|
}, [
|
|
16763
|
-
createBaseVNode("section", _hoisted_1$
|
|
17182
|
+
createBaseVNode("section", _hoisted_1$a, [
|
|
16764
17183
|
createBaseVNode("h3", null, [
|
|
16765
17184
|
!isSupport.value ? (openBlock(), createBlock(_component_name_edit_partial, {
|
|
16766
17185
|
key: 0,
|
|
@@ -16775,9 +17194,10 @@ const _sfc_main$d = /* @__PURE__ */ defineComponent({
|
|
|
16775
17194
|
createTextVNode(toDisplayString$1(_ctx.$t("support")), 1)
|
|
16776
17195
|
], 64)) : createCommentVNode("", true)
|
|
16777
17196
|
]),
|
|
16778
|
-
!isSupport.value && conversationData.value ? (openBlock(), createElementBlock("h4", _hoisted_2$
|
|
17197
|
+
!isSupport.value && conversationData.value ? (openBlock(), createElementBlock("h4", _hoisted_2$7, [
|
|
16779
17198
|
createVNode(_component_participants_partial, {
|
|
16780
17199
|
participants: conversationData.value.participants,
|
|
17200
|
+
inline: "",
|
|
16781
17201
|
"remove-user": "",
|
|
16782
17202
|
"is-new": isNew.value
|
|
16783
17203
|
}, null, 8, ["participants", "is-new"]),
|
|
@@ -16785,13 +17205,9 @@ const _sfc_main$d = /* @__PURE__ */ defineComponent({
|
|
|
16785
17205
|
key: 0,
|
|
16786
17206
|
size: "sm",
|
|
16787
17207
|
variant: "ghost",
|
|
17208
|
+
icon: "edit",
|
|
16788
17209
|
"aria-label": "Toggle edit mode",
|
|
16789
17210
|
onClick: _cache[0] || (_cache[0] = ($event) => toggleEdit())
|
|
16790
|
-
}, {
|
|
16791
|
-
default: withCtx(() => [..._cache[1] || (_cache[1] = [
|
|
16792
|
-
createTextVNode(" edit ", -1)
|
|
16793
|
-
])]),
|
|
16794
|
-
_: 1
|
|
16795
17211
|
})) : createCommentVNode("", true)
|
|
16796
17212
|
])) : createCommentVNode("", true),
|
|
16797
17213
|
!isSupport.value && !isNew.value ? (openBlock(), createBlock(_component_chat_actions_partial, {
|
|
@@ -16803,8 +17219,8 @@ const _sfc_main$d = /* @__PURE__ */ defineComponent({
|
|
|
16803
17219
|
};
|
|
16804
17220
|
}
|
|
16805
17221
|
});
|
|
16806
|
-
const _style_0$
|
|
16807
|
-
const ChatHeaderPartial = /* @__PURE__ */ _export_sfc(_sfc_main$d, [["styles", [_style_0$
|
|
17222
|
+
const _style_0$b = ".chat-header[data-v-dd11b73a]{display:grid;padding:10px 20px}.chat-header .background-container[data-v-dd11b73a]{display:grid;grid-template-columns:5fr 1fr;grid-template-rows:max-content;align-content:start;padding:0 10px;background-color:var(--scm-color-surface);border-radius:5px}.chat-header .background-container h3[data-v-dd11b73a],.chat-header .background-container h4[data-v-dd11b73a]{margin:0;grid-column:1 / 2}.chat-header .background-container h3[data-v-dd11b73a]{grid-row:1;font-family:Open Sans;letter-spacing:-.1px}.chat-header .background-container h4[data-v-dd11b73a]{display:grid;grid-row:2}.chat-header .background-container .chat-actions-partial[data-v-dd11b73a]{justify-self:end;grid-row:1}";
|
|
17223
|
+
const ChatHeaderPartial = /* @__PURE__ */ _export_sfc(_sfc_main$d, [["styles", [_style_0$b]], ["__scopeId", "data-v-dd11b73a"]]);
|
|
16808
17224
|
const _sfc_main$c = /* @__PURE__ */ defineComponent({
|
|
16809
17225
|
__name: "name-edit.partial",
|
|
16810
17226
|
props: {
|
|
@@ -16848,17 +17264,13 @@ const _sfc_main$c = /* @__PURE__ */ defineComponent({
|
|
|
16848
17264
|
return openBlock(), createElementBlock(Fragment, null, [
|
|
16849
17265
|
!edit.value ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [
|
|
16850
17266
|
renderSlot(_ctx.$slots, "default"),
|
|
16851
|
-
_cache[
|
|
17267
|
+
_cache[1] || (_cache[1] = createTextVNode()),
|
|
16852
17268
|
createVNode(_component_button_partial, {
|
|
16853
17269
|
size: "sm",
|
|
16854
17270
|
variant: "ghost",
|
|
17271
|
+
icon: "edit",
|
|
16855
17272
|
"aria-label": "Edit conversation name",
|
|
16856
17273
|
onClick: toggleEdit
|
|
16857
|
-
}, {
|
|
16858
|
-
default: withCtx(() => [..._cache[1] || (_cache[1] = [
|
|
16859
|
-
createTextVNode(" Edit ", -1)
|
|
16860
|
-
])]),
|
|
16861
|
-
_: 1
|
|
16862
17274
|
})
|
|
16863
17275
|
], 64)) : createCommentVNode("", true),
|
|
16864
17276
|
edit.value ? (openBlock(), createElementBlock(Fragment, { key: 1 }, [
|
|
@@ -16878,7 +17290,7 @@ const _sfc_main$c = /* @__PURE__ */ defineComponent({
|
|
|
16878
17290
|
disabled: !name.value?.length,
|
|
16879
17291
|
onClick: save
|
|
16880
17292
|
}, {
|
|
16881
|
-
default: withCtx(() => [..._cache[
|
|
17293
|
+
default: withCtx(() => [..._cache[2] || (_cache[2] = [
|
|
16882
17294
|
createTextVNode(" Save ", -1)
|
|
16883
17295
|
])]),
|
|
16884
17296
|
_: 1
|
|
@@ -16889,7 +17301,7 @@ const _sfc_main$c = /* @__PURE__ */ defineComponent({
|
|
|
16889
17301
|
"aria-label": "Cancel editing",
|
|
16890
17302
|
onClick: toggleEdit
|
|
16891
17303
|
}, {
|
|
16892
|
-
default: withCtx(() => [..._cache[
|
|
17304
|
+
default: withCtx(() => [..._cache[3] || (_cache[3] = [
|
|
16893
17305
|
createTextVNode(" X ", -1)
|
|
16894
17306
|
])]),
|
|
16895
17307
|
_: 1
|
|
@@ -16899,7 +17311,7 @@ const _sfc_main$c = /* @__PURE__ */ defineComponent({
|
|
|
16899
17311
|
};
|
|
16900
17312
|
}
|
|
16901
17313
|
});
|
|
16902
|
-
const _hoisted_1$
|
|
17314
|
+
const _hoisted_1$9 = { class: "notice-partial" };
|
|
16903
17315
|
const _sfc_main$b = /* @__PURE__ */ defineComponent({
|
|
16904
17316
|
__name: "notice.partial",
|
|
16905
17317
|
props: {
|
|
@@ -16907,14 +17319,14 @@ const _sfc_main$b = /* @__PURE__ */ defineComponent({
|
|
|
16907
17319
|
},
|
|
16908
17320
|
setup(__props) {
|
|
16909
17321
|
return (_ctx, _cache) => {
|
|
16910
|
-
return openBlock(), createElementBlock("section", _hoisted_1$
|
|
17322
|
+
return openBlock(), createElementBlock("section", _hoisted_1$9, [
|
|
16911
17323
|
renderSlot(_ctx.$slots, "default", {}, void 0, true)
|
|
16912
17324
|
]);
|
|
16913
17325
|
};
|
|
16914
17326
|
}
|
|
16915
17327
|
});
|
|
16916
|
-
const _style_0$
|
|
16917
|
-
const NoticePartial = /* @__PURE__ */ _export_sfc(_sfc_main$b, [["styles", [_style_0$
|
|
17328
|
+
const _style_0$a = ".notice-partial[data-v-2ad9f6c8]{display:grid}";
|
|
17329
|
+
const NoticePartial = /* @__PURE__ */ _export_sfc(_sfc_main$b, [["styles", [_style_0$a]], ["__scopeId", "data-v-2ad9f6c8"]]);
|
|
16918
17330
|
const _sfc_main$a = /* @__PURE__ */ defineComponent({
|
|
16919
17331
|
...{ inheritAttrs: false },
|
|
16920
17332
|
__name: "system-message.partial",
|
|
@@ -16958,8 +17370,8 @@ const _sfc_main$a = /* @__PURE__ */ defineComponent({
|
|
|
16958
17370
|
};
|
|
16959
17371
|
}
|
|
16960
17372
|
});
|
|
16961
|
-
const _hoisted_1$
|
|
16962
|
-
const _hoisted_2$
|
|
17373
|
+
const _hoisted_1$8 = { class: "chat-actions-partial" };
|
|
17374
|
+
const _hoisted_2$6 = { class: "options-container" };
|
|
16963
17375
|
const _sfc_main$9 = /* @__PURE__ */ defineComponent({
|
|
16964
17376
|
__name: "chat-actions.partial",
|
|
16965
17377
|
props: {
|
|
@@ -16990,7 +17402,7 @@ const _sfc_main$9 = /* @__PURE__ */ defineComponent({
|
|
|
16990
17402
|
const _component_button_partial = resolveComponent("button-partial");
|
|
16991
17403
|
const _component_overlay_container_partial = resolveComponent("overlay-container-partial");
|
|
16992
17404
|
const _component_dialog_partial = resolveComponent("dialog-partial");
|
|
16993
|
-
return openBlock(), createElementBlock("section", _hoisted_1$
|
|
17405
|
+
return openBlock(), createElementBlock("section", _hoisted_1$8, [
|
|
16994
17406
|
createVNode(_component_button_partial, {
|
|
16995
17407
|
ref_key: "attachTo",
|
|
16996
17408
|
ref: attachTo,
|
|
@@ -17010,7 +17422,7 @@ const _sfc_main$9 = /* @__PURE__ */ defineComponent({
|
|
|
17010
17422
|
onClose: toggle
|
|
17011
17423
|
}, {
|
|
17012
17424
|
default: withCtx(() => [
|
|
17013
|
-
createBaseVNode("section", _hoisted_2$
|
|
17425
|
+
createBaseVNode("section", _hoisted_2$6, [
|
|
17014
17426
|
createBaseVNode("ul", null, [
|
|
17015
17427
|
createBaseVNode("li", null, toDisplayString$1(_ctx.$t("mute")), 1),
|
|
17016
17428
|
createBaseVNode("li", null, toDisplayString$1(_ctx.$t("delete")), 1),
|
|
@@ -17051,8 +17463,8 @@ const _sfc_main$9 = /* @__PURE__ */ defineComponent({
|
|
|
17051
17463
|
};
|
|
17052
17464
|
}
|
|
17053
17465
|
});
|
|
17054
|
-
const _style_0$
|
|
17055
|
-
const ChatActionsPartial = /* @__PURE__ */ _export_sfc(_sfc_main$9, [["styles", [_style_0$
|
|
17466
|
+
const _style_0$9 = ".chat-actions-partial[data-v-871e6a65]{display:grid}.options-container[data-v-871e6a65]{width:max-content;min-width:200px;background-color:var(--scm-color-surface);box-shadow:0 0 5px var(--scm-color-muted)}";
|
|
17467
|
+
const ChatActionsPartial = /* @__PURE__ */ _export_sfc(_sfc_main$9, [["styles", [_style_0$9]], ["__scopeId", "data-v-871e6a65"]]);
|
|
17056
17468
|
const _sfc_main$8 = /* @__PURE__ */ defineComponent({
|
|
17057
17469
|
__name: "overlay-container.partial",
|
|
17058
17470
|
props: {
|
|
@@ -17187,10 +17599,10 @@ const _sfc_main$8 = /* @__PURE__ */ defineComponent({
|
|
|
17187
17599
|
};
|
|
17188
17600
|
}
|
|
17189
17601
|
});
|
|
17190
|
-
const _style_0$
|
|
17191
|
-
const OverlayContainerPartial = /* @__PURE__ */ _export_sfc(_sfc_main$8, [["styles", [_style_0$
|
|
17192
|
-
const _hoisted_1$
|
|
17193
|
-
const _hoisted_2$
|
|
17602
|
+
const _style_0$8 = ".overlay-background{position:fixed;top:0;left:0;display:grid;width:100%;height:100%;background-color:#00000080;z-index:1000}.overlay-background.none,.overlay-background.tablet{background-color:transparent}@media only screen and (min-width: 600px) and (max-width: 1023px){.overlay-background.tablet{background-color:#00000080}}.overlay-background.desktop{background-color:transparent}@media only screen and (min-width: 600px) and (max-width: 1023px),only screen and (min-width: 1024px){.overlay-background.desktop{background-color:#00000080}}.overlay-background .content-container{z-index:1100;position:absolute}";
|
|
17603
|
+
const OverlayContainerPartial = /* @__PURE__ */ _export_sfc(_sfc_main$8, [["styles", [_style_0$8]]]);
|
|
17604
|
+
const _hoisted_1$7 = ["type", "disabled", "aria-busy", "aria-label"];
|
|
17605
|
+
const _hoisted_2$5 = {
|
|
17194
17606
|
key: 0,
|
|
17195
17607
|
class: "scm-btn__spinner",
|
|
17196
17608
|
"aria-hidden": "true"
|
|
@@ -17243,19 +17655,19 @@ const _sfc_main$7 = /* @__PURE__ */ defineComponent({
|
|
|
17243
17655
|
class: normalizeClass(classes.value),
|
|
17244
17656
|
onClick
|
|
17245
17657
|
}, [
|
|
17246
|
-
props.loading ? (openBlock(), createElementBlock("span", _hoisted_2$
|
|
17658
|
+
props.loading ? (openBlock(), createElementBlock("span", _hoisted_2$5)) : props.icon ? (openBlock(), createBlock(_component_icons_partial, {
|
|
17247
17659
|
key: 1,
|
|
17248
17660
|
type: props.icon
|
|
17249
17661
|
}, null, 8, ["type"])) : (openBlock(), createElementBlock("span", _hoisted_3$2, [
|
|
17250
17662
|
renderSlot(_ctx.$slots, "default", {}, void 0, true)
|
|
17251
17663
|
]))
|
|
17252
|
-
], 10, _hoisted_1$
|
|
17664
|
+
], 10, _hoisted_1$7);
|
|
17253
17665
|
};
|
|
17254
17666
|
}
|
|
17255
17667
|
});
|
|
17256
|
-
const _style_0$
|
|
17257
|
-
const ButtonPartial = /* @__PURE__ */ _export_sfc(_sfc_main$7, [["styles", [_style_0$
|
|
17258
|
-
const _hoisted_1$
|
|
17668
|
+
const _style_0$7 = ".scm-btn[data-v-a79bdb66]{--scm-btn-bg: var(--scm-color-primary);--scm-btn-color: white;--scm-btn-radius: 0;--scm-btn-padding-y: 4px;--scm-btn-padding-x: 10px;--scm-btn-font-size: .875em;--scm-btn-height: 40px;--scm-btn-line-height: 42px;--scm-btn-transition: .12s ease-in-out;appearance:none;border:none;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;gap:6px;background-color:var(--scm-btn-bg);color:var(--scm-btn-color);font:inherit;padding:var(--scm-btn-padding-y) var(--scm-btn-padding-x);font-size:var(--scm-btn-font-size);border-radius:var(--scm-btn-radius);height:var(--scm-btn-height);line-height:var(--scm-btn-line-height);transition:background-color var(--scm-btn-transition),opacity var(--scm-btn-transition),box-shadow var(--scm-btn-transition);text-decoration:none;white-space:nowrap}.scm-btn[data-v-a79bdb66]:hover:not(:disabled){background-color:color-mix(in srgb,var(--scm-btn-bg) 85%,#000)}.scm-btn[data-v-a79bdb66]:active:not(:disabled){background-color:color-mix(in srgb,var(--scm-btn-bg) 70%,#000)}.scm-btn[data-v-a79bdb66]:focus-visible{outline:2px solid var(--scm-color-primary);outline-offset:2px}.scm-btn[data-v-a79bdb66]:disabled{opacity:.55;cursor:not-allowed}.scm-btn--secondary[data-v-a79bdb66]{--scm-btn-bg: var(--scm-color-surface);--scm-btn-color: var(--scm-color-muted)}.scm-btn--ghost[data-v-a79bdb66]{--scm-btn-bg: transparent;--scm-btn-color: var(--scm-color-primary)}.scm-btn--danger[data-v-a79bdb66]{--scm-btn-bg: var(--scm-color-danger);--scm-btn-color: white}.scm-btn--sm[data-v-a79bdb66]{--scm-btn-padding-y: 2px;--scm-btn-padding-x: 8px;--scm-btn-font-size: .75em}.scm-btn--lg[data-v-a79bdb66]{--scm-btn-padding-y: 8px;--scm-btn-padding-x: 16px;--scm-btn-font-size: 1em}.scm-btn--block[data-v-a79bdb66]{width:100%;display:inline-flex}.scm-btn__spinner[data-v-a79bdb66]{width:14px;height:14px;border:2px solid currentColor;border-right-color:transparent;border-radius:50%;animation:scm-spin-a79bdb66 .6s linear infinite}.scm-btn--icon[data-v-a79bdb66]{--scm-btn-padding-x: 8px;width:var(--scm-btn-height)}.scm-btn--icon[data-v-a79bdb66] .icon-partial svg{stroke:currentColor}.scm-btn--icon[data-v-a79bdb66] .icon-partial svg.useFill{fill:currentColor}@keyframes scm-spin-a79bdb66{to{transform:rotate(360deg)}}";
|
|
17669
|
+
const ButtonPartial = /* @__PURE__ */ _export_sfc(_sfc_main$7, [["styles", [_style_0$7]], ["__scopeId", "data-v-a79bdb66"]]);
|
|
17670
|
+
const _hoisted_1$6 = { class: "dialog-partial" };
|
|
17259
17671
|
const _sfc_main$6 = /* @__PURE__ */ defineComponent({
|
|
17260
17672
|
__name: "dialog.partial",
|
|
17261
17673
|
emits: ["accept", "decline"],
|
|
@@ -17269,7 +17681,7 @@ const _sfc_main$6 = /* @__PURE__ */ defineComponent({
|
|
|
17269
17681
|
}
|
|
17270
17682
|
return (_ctx, _cache) => {
|
|
17271
17683
|
const _component_button_partial = resolveComponent("button-partial");
|
|
17272
|
-
return openBlock(), createElementBlock("section", _hoisted_1$
|
|
17684
|
+
return openBlock(), createElementBlock("section", _hoisted_1$6, [
|
|
17273
17685
|
renderSlot(_ctx.$slots, "default", {}, void 0, true),
|
|
17274
17686
|
createVNode(_component_button_partial, { onClick: onAccept }, {
|
|
17275
17687
|
default: withCtx(() => [..._cache[0] || (_cache[0] = [
|
|
@@ -17287,10 +17699,10 @@ const _sfc_main$6 = /* @__PURE__ */ defineComponent({
|
|
|
17287
17699
|
};
|
|
17288
17700
|
}
|
|
17289
17701
|
});
|
|
17290
|
-
const _style_0$
|
|
17291
|
-
const DialogPartial = /* @__PURE__ */ _export_sfc(_sfc_main$6, [["styles", [_style_0$
|
|
17292
|
-
const _hoisted_1$
|
|
17293
|
-
const _hoisted_2$
|
|
17702
|
+
const _style_0$6 = ".dialog-partial[data-v-ae4dfdf7]{padding:20px;background-color:var(--scm-color-surface);box-shadow:0 0 5px var(--scm-color-muted)}";
|
|
17703
|
+
const DialogPartial = /* @__PURE__ */ _export_sfc(_sfc_main$6, [["styles", [_style_0$6]], ["__scopeId", "data-v-ae4dfdf7"]]);
|
|
17704
|
+
const _hoisted_1$5 = { class: "chat-input" };
|
|
17705
|
+
const _hoisted_2$4 = { class: "background-container" };
|
|
17294
17706
|
const _hoisted_3$1 = ["value", "placeholder"];
|
|
17295
17707
|
const _sfc_main$5 = /* @__PURE__ */ defineComponent({
|
|
17296
17708
|
__name: "chat-input.partial",
|
|
@@ -17325,8 +17737,8 @@ const _sfc_main$5 = /* @__PURE__ */ defineComponent({
|
|
|
17325
17737
|
watch(() => props.modelValue, () => nextTick(resize2));
|
|
17326
17738
|
return (_ctx, _cache) => {
|
|
17327
17739
|
const _component_button_partial = resolveComponent("button-partial");
|
|
17328
|
-
return openBlock(), createElementBlock("div", _hoisted_1$
|
|
17329
|
-
createBaseVNode("section", _hoisted_2$
|
|
17740
|
+
return openBlock(), createElementBlock("div", _hoisted_1$5, [
|
|
17741
|
+
createBaseVNode("section", _hoisted_2$4, [
|
|
17330
17742
|
createBaseVNode("textarea", {
|
|
17331
17743
|
ref_key: "textareaRef",
|
|
17332
17744
|
ref: textareaRef,
|
|
@@ -17348,26 +17760,10 @@ const _sfc_main$5 = /* @__PURE__ */ defineComponent({
|
|
|
17348
17760
|
};
|
|
17349
17761
|
}
|
|
17350
17762
|
});
|
|
17351
|
-
const _style_0$
|
|
17352
|
-
const ChatInputPartial = /* @__PURE__ */ _export_sfc(_sfc_main$5, [["styles", [_style_0$
|
|
17763
|
+
const _style_0$5 = ".chat-input[data-v-b6ae32fa]{padding:20px}.chat-input .background-container[data-v-b6ae32fa]{border-radius:5px;display:grid;grid-template-columns:1fr max-content;grid-template-rows:max-content;background-color:var(--scm-color-surface)}.chat-input .background-container textarea[data-v-b6ae32fa]{border:0;padding:10px;background-color:var(--scm-color-surface);outline:none;font-size:1em}.chat-input .background-container button[data-v-b6ae32fa]{align-self:end}";
|
|
17764
|
+
const ChatInputPartial = /* @__PURE__ */ _export_sfc(_sfc_main$5, [["styles", [_style_0$5]], ["__scopeId", "data-v-b6ae32fa"]]);
|
|
17765
|
+
const _hoisted_1$4 = { class: "user-avatar" };
|
|
17353
17766
|
const _sfc_main$4 = /* @__PURE__ */ defineComponent({
|
|
17354
|
-
__name: "user-name.partial",
|
|
17355
|
-
props: {
|
|
17356
|
-
userId: { type: String }
|
|
17357
|
-
},
|
|
17358
|
-
setup(__props) {
|
|
17359
|
-
const props = __props;
|
|
17360
|
-
const usersCache = useUsersCacheStore();
|
|
17361
|
-
onMounted(() => {
|
|
17362
|
-
usersCache.ensure([props.userId]);
|
|
17363
|
-
});
|
|
17364
|
-
return (_ctx, _cache) => {
|
|
17365
|
-
return toDisplayString$1(unref(usersCache).name(props.userId));
|
|
17366
|
-
};
|
|
17367
|
-
}
|
|
17368
|
-
});
|
|
17369
|
-
const _hoisted_1$3 = { class: "user-avatar" };
|
|
17370
|
-
const _sfc_main$3 = /* @__PURE__ */ defineComponent({
|
|
17371
17767
|
__name: "user-avatar.partial",
|
|
17372
17768
|
props: {
|
|
17373
17769
|
userId: { type: String }
|
|
@@ -17392,19 +17788,19 @@ const _sfc_main$3 = /* @__PURE__ */ defineComponent({
|
|
|
17392
17788
|
usersCache.ensure([props.userId]);
|
|
17393
17789
|
});
|
|
17394
17790
|
return (_ctx, _cache) => {
|
|
17395
|
-
return openBlock(), createElementBlock("span", _hoisted_1$
|
|
17791
|
+
return openBlock(), createElementBlock("span", _hoisted_1$4, [
|
|
17396
17792
|
createBaseVNode("span", {
|
|
17397
17793
|
class: "user-avatar__circle",
|
|
17398
17794
|
style: normalizeStyle({ backgroundColor: `hsl(${hue.value}, 45%, 60%)` })
|
|
17399
17795
|
}, toDisplayString$1(initials.value), 5),
|
|
17400
|
-
createVNode(_sfc_main$
|
|
17796
|
+
createVNode(_sfc_main$g, { "user-id": __props.userId }, null, 8, ["user-id"])
|
|
17401
17797
|
]);
|
|
17402
17798
|
};
|
|
17403
17799
|
}
|
|
17404
17800
|
});
|
|
17405
|
-
const _style_0$
|
|
17406
|
-
const UserAvatarPartial = /* @__PURE__ */ _export_sfc(_sfc_main$
|
|
17407
|
-
const _hoisted_1$
|
|
17801
|
+
const _style_0$4 = ".user-avatar[data-v-1fc1d2df]{display:inline-flex;align-items:center;gap:6px}.user-avatar__circle[data-v-1fc1d2df]{display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;border-radius:50%;font-size:.625em;font-weight:600;color:#fff;flex-shrink:0;line-height:1}";
|
|
17802
|
+
const UserAvatarPartial = /* @__PURE__ */ _export_sfc(_sfc_main$4, [["styles", [_style_0$4]], ["__scopeId", "data-v-1fc1d2df"]]);
|
|
17803
|
+
const _hoisted_1$3 = {
|
|
17408
17804
|
key: 0,
|
|
17409
17805
|
xmlns: "http://www.w3.org/2000/svg",
|
|
17410
17806
|
class: "h-6 w-6",
|
|
@@ -17413,7 +17809,7 @@ const _hoisted_1$2 = {
|
|
|
17413
17809
|
stroke: "currentColor",
|
|
17414
17810
|
"stroke-width": "2"
|
|
17415
17811
|
};
|
|
17416
|
-
const _hoisted_2$
|
|
17812
|
+
const _hoisted_2$3 = {
|
|
17417
17813
|
key: 1,
|
|
17418
17814
|
xmlns: "http://www.w3.org/2000/svg",
|
|
17419
17815
|
class: "h-6 w-6",
|
|
@@ -17875,7 +18271,7 @@ const _hoisted_53 = {
|
|
|
17875
18271
|
stroke: "currentColor",
|
|
17876
18272
|
class: "size-6"
|
|
17877
18273
|
};
|
|
17878
|
-
const _sfc_main$
|
|
18274
|
+
const _sfc_main$3 = /* @__PURE__ */ defineComponent({
|
|
17879
18275
|
__name: "icons.partial",
|
|
17880
18276
|
props: {
|
|
17881
18277
|
type: { type: String },
|
|
@@ -17894,14 +18290,14 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
|
|
|
17894
18290
|
return openBlock(), createElementBlock("span", {
|
|
17895
18291
|
class: normalizeClass(["icon-partial", [__props.type, __props.colorScheme || "colorScheme1", __props.size || "medium", rotateClass.value, { animate: __props.animate }]])
|
|
17896
18292
|
}, [
|
|
17897
|
-
__props.type === "arrow-right" ? (openBlock(), createElementBlock("svg", _hoisted_1$
|
|
18293
|
+
__props.type === "arrow-right" ? (openBlock(), createElementBlock("svg", _hoisted_1$3, [..._cache[0] || (_cache[0] = [
|
|
17898
18294
|
createBaseVNode("path", {
|
|
17899
18295
|
"stroke-linecap": "round",
|
|
17900
18296
|
"stroke-linejoin": "round",
|
|
17901
18297
|
d: "M9 5l7 7-7 7"
|
|
17902
18298
|
}, null, -1)
|
|
17903
18299
|
])])) : createCommentVNode("", true),
|
|
17904
|
-
__props.type === "arrow-left" ? (openBlock(), createElementBlock("svg", _hoisted_2$
|
|
18300
|
+
__props.type === "arrow-left" ? (openBlock(), createElementBlock("svg", _hoisted_2$3, [..._cache[1] || (_cache[1] = [
|
|
17905
18301
|
createBaseVNode("path", {
|
|
17906
18302
|
"stroke-linecap": "round",
|
|
17907
18303
|
"stroke-linejoin": "round",
|
|
@@ -18293,24 +18689,58 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
|
|
|
18293
18689
|
};
|
|
18294
18690
|
}
|
|
18295
18691
|
});
|
|
18296
|
-
const _style_0$
|
|
18297
|
-
const IconsPartial = /* @__PURE__ */ _export_sfc(_sfc_main$
|
|
18298
|
-
const _hoisted_1$
|
|
18299
|
-
const _hoisted_2$
|
|
18300
|
-
const _sfc_main$
|
|
18692
|
+
const _style_0$3 = ".icon-partial[data-v-f8bafd55]{display:grid;align-self:center;justify-content:center}.icon-partial svg[data-v-f8bafd55]{align-self:center;justify-self:center;stroke-width:1.5}.icon-partial.rotate90 svg[data-v-f8bafd55]{transform:rotate(90deg)}.icon-partial.rotate180 svg[data-v-f8bafd55]{transform:rotate(180deg)}.icon-partial.animate svg[data-v-f8bafd55]{transition:transform .2s ease,fill .2s ease,stroke .2s ease}@keyframes upAndDown-f8bafd55{0%{transform:translateY(0)}to{transform:translateY(-20px)}}.icon-partial.animate .upload .arrow-up[data-v-f8bafd55]{animation:upAndDown-f8bafd55 1s infinite ease-in-out}.icon-partial.big[data-v-f8bafd55]{width:30px;height:30px}.icon-partial.big svg[data-v-f8bafd55]{width:30px;height:30px}.icon-partial.larger[data-v-f8bafd55]{width:26px;height:26px}.icon-partial.larger svg[data-v-f8bafd55]{width:26px;height:26px}.icon-partial.large[data-v-f8bafd55]{width:24px;height:24px}.icon-partial.large svg[data-v-f8bafd55]{width:24px;height:24px}.icon-partial.xl[data-v-f8bafd55]{width:60px;height:60px}.icon-partial.xl svg[data-v-f8bafd55]{width:60px;height:60px}.icon-partial.medium[data-v-f8bafd55]{width:20px;height:20px}.icon-partial.medium svg[data-v-f8bafd55]{width:20px;height:20px}.icon-partial.small[data-v-f8bafd55]{width:16px;height:16px}.icon-partial.small svg[data-v-f8bafd55]{width:16px;height:16px}.icon-partial.smaller[data-v-f8bafd55]{width:10px;height:10px}.icon-partial.smaller svg[data-v-f8bafd55]{width:10px;height:10px}.icon-partial.colorScheme1 svg[data-v-f8bafd55]{stroke:var(--scm-icon-color-1, #333)}.icon-partial.colorScheme1 svg.useFill[data-v-f8bafd55]{fill:var(--scm-icon-color-1, #333);stroke-width:0}.icon-partial.colorScheme2 svg[data-v-f8bafd55]{stroke:var(--scm-icon-color-2, #666)}.icon-partial.colorScheme2 svg.useFill[data-v-f8bafd55]{fill:var(--scm-icon-color-2, #666);stroke-width:0}.icon-partial.colorScheme4 svg[data-v-f8bafd55]{stroke:var(--scm-icon-color-1, #333)}.icon-partial.colorScheme4 svg.useFill[data-v-f8bafd55]{fill:var(--scm-icon-color-1, #333);stroke-width:0}.icon-partial.white svg[data-v-f8bafd55]{stroke:#fff}.icon-partial.white svg.useFill[data-v-f8bafd55]{fill:#fff;stroke-width:0}.icon-partial.grey svg[data-v-f8bafd55]{stroke:var(--scm-color-muted, #999)}.icon-partial.grey svg.useFill[data-v-f8bafd55]{fill:var(--scm-color-muted, #999);stroke-width:0}.icon-partial.aiColor svg[data-v-f8bafd55]{stroke:var(--scm-icon-ai-color, #8b5cf6)}.icon-partial.aiColor svg.useFill[data-v-f8bafd55]{fill:var(--scm-icon-ai-color, #8b5cf6);stroke-width:0}.icon-partial.red svg[data-v-f8bafd55]{stroke:var(--scm-color-danger, #e53935)}.icon-partial.red svg.useFill[data-v-f8bafd55]{fill:var(--scm-color-danger, #e53935);stroke-width:0}.icon-partial.green svg[data-v-f8bafd55]{stroke:#43a047}.icon-partial.green svg.useFill[data-v-f8bafd55]{fill:#43a047;stroke-width:0}";
|
|
18693
|
+
const IconsPartial = /* @__PURE__ */ _export_sfc(_sfc_main$3, [["styles", [_style_0$3]], ["__scopeId", "data-v-f8bafd55"]]);
|
|
18694
|
+
const _hoisted_1$2 = { class: "connection-status" };
|
|
18695
|
+
const _hoisted_2$2 = { class: "status" };
|
|
18696
|
+
const _sfc_main$2 = /* @__PURE__ */ defineComponent({
|
|
18301
18697
|
__name: "connection-status.partial",
|
|
18302
18698
|
setup(__props) {
|
|
18303
18699
|
const mainStore = useMainStore();
|
|
18304
18700
|
const connection = computed(() => mainStore.state);
|
|
18305
18701
|
return (_ctx, _cache) => {
|
|
18306
|
-
return openBlock(), createElementBlock("section", _hoisted_1$
|
|
18307
|
-
createBaseVNode("div", _hoisted_2$
|
|
18702
|
+
return openBlock(), createElementBlock("section", _hoisted_1$2, [
|
|
18703
|
+
createBaseVNode("div", _hoisted_2$2, toDisplayString$1(_ctx.$t(`status.${connection.value}`)), 1)
|
|
18308
18704
|
]);
|
|
18309
18705
|
};
|
|
18310
18706
|
}
|
|
18311
18707
|
});
|
|
18312
|
-
const _style_0$
|
|
18313
|
-
const ConnectionStatusPartial = /* @__PURE__ */ _export_sfc(_sfc_main$
|
|
18708
|
+
const _style_0$2 = ".connection-status[data-v-81fdb902]{background-color:var(--scm-color-danger);color:#fff;padding:0 10px;font-size:.7rem;align-content:center}";
|
|
18709
|
+
const ConnectionStatusPartial = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["styles", [_style_0$2]], ["__scopeId", "data-v-81fdb902"]]);
|
|
18710
|
+
const _hoisted_1$1 = {
|
|
18711
|
+
key: 0,
|
|
18712
|
+
class: "conversations-button-partial"
|
|
18713
|
+
};
|
|
18714
|
+
const _hoisted_2$1 = {
|
|
18715
|
+
key: 0,
|
|
18716
|
+
class: "unread"
|
|
18717
|
+
};
|
|
18718
|
+
const _sfc_main$1 = /* @__PURE__ */ defineComponent({
|
|
18719
|
+
__name: "conversations-button.partial",
|
|
18720
|
+
setup(__props) {
|
|
18721
|
+
const mainStore = useMainStore();
|
|
18722
|
+
const conversationsStore = useConversationsStore();
|
|
18723
|
+
const showButton = computed(() => mainStore.hasChat || conversationsStore.conversations.length > 1);
|
|
18724
|
+
const unreadCount = computed(() => conversationsStore.totalUnreadCount);
|
|
18725
|
+
function showConversations() {
|
|
18726
|
+
mainStore.showConversations();
|
|
18727
|
+
}
|
|
18728
|
+
return (_ctx, _cache) => {
|
|
18729
|
+
const _component_button_partial = resolveComponent("button-partial");
|
|
18730
|
+
return showButton.value ? (openBlock(), createElementBlock("section", _hoisted_1$1, [
|
|
18731
|
+
createVNode(_component_button_partial, {
|
|
18732
|
+
icon: "chat",
|
|
18733
|
+
variant: "secondary",
|
|
18734
|
+
"aria-label": "Conversations",
|
|
18735
|
+
onClick: showConversations
|
|
18736
|
+
}),
|
|
18737
|
+
unreadCount.value ? (openBlock(), createElementBlock("span", _hoisted_2$1, toDisplayString$1(unreadCount.value), 1)) : createCommentVNode("", true)
|
|
18738
|
+
])) : createCommentVNode("", true);
|
|
18739
|
+
};
|
|
18740
|
+
}
|
|
18741
|
+
});
|
|
18742
|
+
const _style_0$1 = ".conversations-button-partial[data-v-864b2cbd]{position:relative;display:inline-flex}.conversations-button-partial .unread[data-v-864b2cbd]{position:absolute;top:2px;right:2px;min-width:16px;height:16px;padding:0 4px;border-radius:8px;background-color:var(--scm-color-own);color:#fff;font-size:.625em;line-height:16px;text-align:center;pointer-events:none}";
|
|
18743
|
+
const ConversationsButtonPartial = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["styles", [_style_0$1]], ["__scopeId", "data-v-864b2cbd"]]);
|
|
18314
18744
|
function resolveFeatures(config) {
|
|
18315
18745
|
if (config.features?.length) return [...new Set(config.features)];
|
|
18316
18746
|
switch (config.mode) {
|
|
@@ -18343,7 +18773,7 @@ function applyConfig(config, pinia) {
|
|
|
18343
18773
|
const MODULES = [
|
|
18344
18774
|
{ name: "chat", component: ChatModule },
|
|
18345
18775
|
{ name: "conversations", component: ConversationsModule },
|
|
18346
|
-
{ name: "chats", component: _sfc_main$
|
|
18776
|
+
{ name: "chats", component: _sfc_main$j },
|
|
18347
18777
|
{ name: "contacts", component: ContactsModule }
|
|
18348
18778
|
];
|
|
18349
18779
|
const PARTIALS = [
|
|
@@ -18359,9 +18789,10 @@ const PARTIALS = [
|
|
|
18359
18789
|
{ name: "dialog", component: DialogPartial },
|
|
18360
18790
|
{ name: "chat-input", component: ChatInputPartial },
|
|
18361
18791
|
{ name: "user-avatar", component: UserAvatarPartial },
|
|
18362
|
-
{ name: "user-name", component: _sfc_main$
|
|
18792
|
+
{ name: "user-name", component: _sfc_main$g },
|
|
18363
18793
|
{ name: "icons", component: IconsPartial },
|
|
18364
|
-
{ name: "connection-status", component: ConnectionStatusPartial }
|
|
18794
|
+
{ name: "connection-status", component: ConnectionStatusPartial },
|
|
18795
|
+
{ name: "conversations-button", component: ConversationsButtonPartial }
|
|
18365
18796
|
];
|
|
18366
18797
|
function registerComponents(app) {
|
|
18367
18798
|
loadViaDeclarationSync(MODULES, void 0, "module", app);
|
|
@@ -18496,10 +18927,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
18496
18927
|
const mainStore = useMainStore();
|
|
18497
18928
|
const userStore = useUserStore();
|
|
18498
18929
|
const conversationsStore = useConversationsStore();
|
|
18499
|
-
|
|
18500
|
-
connect,
|
|
18501
|
-
authenticate
|
|
18502
|
-
} = useWebSocket();
|
|
18930
|
+
useWebSocket();
|
|
18503
18931
|
const realWidth = useResize().realWidth;
|
|
18504
18932
|
const viewMode = computed(() => mainStore.viewMode);
|
|
18505
18933
|
const leftTarget = computed(() => mainStore.leftTarget);
|
|
@@ -18542,8 +18970,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
18542
18970
|
if (props.config) applyConfig(props.config);
|
|
18543
18971
|
const token = await resolveToken() ?? props.config?.token ?? mainStore.authToken;
|
|
18544
18972
|
if (token) mainStore.authToken = token;
|
|
18545
|
-
const
|
|
18546
|
-
const userId = decodeSub(token) ?? props.config?.userId ?? userStore.user ?? urlUser;
|
|
18973
|
+
const userId = decodeSub(token) ?? props.config?.userId ?? userStore.user;
|
|
18547
18974
|
if (!userId) {
|
|
18548
18975
|
if (props.config) console.warn("[studio-chat] config has no usable identity (getToken/token sub or userId)");
|
|
18549
18976
|
return;
|
|
@@ -18551,13 +18978,19 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
18551
18978
|
started = true;
|
|
18552
18979
|
userStore.user = userId;
|
|
18553
18980
|
if (props.config?.user) useUsersCacheStore().setOne({ ...props.config.user, id: userId });
|
|
18554
|
-
|
|
18981
|
+
chatSession.start({
|
|
18555
18982
|
url: mainStore.wsUrl,
|
|
18556
|
-
|
|
18557
|
-
|
|
18558
|
-
|
|
18559
|
-
|
|
18560
|
-
|
|
18983
|
+
fallbackToken: () => mainStore.authToken ?? userId,
|
|
18984
|
+
ownUserId: () => userStore.user,
|
|
18985
|
+
onMessage: handleMessages,
|
|
18986
|
+
onStateChange: (state) => {
|
|
18987
|
+
mainStore.state = state === "ready" ? "connected" : "disconnected";
|
|
18988
|
+
},
|
|
18989
|
+
// the session came back (re-auth or reconnect) — pull everything missed meanwhile
|
|
18990
|
+
onSessionRestored: () => {
|
|
18991
|
+
conversationsStore.handleReconnect().catch(() => {
|
|
18992
|
+
});
|
|
18993
|
+
}
|
|
18561
18994
|
});
|
|
18562
18995
|
if (mainStore.isSupportOnly) bootstrapSupport();
|
|
18563
18996
|
} finally {
|
|
@@ -18567,25 +19000,27 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
18567
19000
|
watch(() => props.config, start, { immediate: true });
|
|
18568
19001
|
return (_ctx, _cache) => {
|
|
18569
19002
|
const _component_actions_partial = resolveComponent("actions-partial");
|
|
19003
|
+
const _component_connection_status_partial = resolveComponent("connection-status-partial");
|
|
18570
19004
|
const _component_contacts_module = resolveComponent("contacts-module");
|
|
18571
19005
|
return openBlock(), createElementBlock("div", {
|
|
18572
|
-
class: normalizeClass(["studio-chat-root", [viewMode.value, leftTarget.value]])
|
|
19006
|
+
class: normalizeClass(["studio-chat-root", [viewMode.value, leftTarget.value, unref(mainStore).state]])
|
|
18573
19007
|
}, [
|
|
18574
19008
|
createBaseVNode("section", _hoisted_1, [
|
|
18575
|
-
createVNode(_component_actions_partial)
|
|
19009
|
+
createVNode(_component_actions_partial),
|
|
19010
|
+
unref(mainStore).state === "disconnected" ? (openBlock(), createBlock(_component_connection_status_partial, { key: 0 })) : createCommentVNode("", true)
|
|
18576
19011
|
]),
|
|
18577
19012
|
unref(mainStore).leftTarget ? (openBlock(), createElementBlock("section", _hoisted_2, [
|
|
18578
19013
|
unref(mainStore).leftTarget === "conversations" ? (openBlock(), createBlock(ConversationsModule, { key: 0 })) : createCommentVNode("", true),
|
|
18579
19014
|
unref(mainStore).leftTarget === "contacts-new" || unref(mainStore).leftTarget === "contacts-edit" ? (openBlock(), createBlock(_component_contacts_module, { key: 1 })) : createCommentVNode("", true)
|
|
18580
19015
|
])) : createCommentVNode("", true),
|
|
18581
|
-
unref(mainStore).mainTarget === "chat" ? (openBlock(), createBlock(_sfc_main$
|
|
19016
|
+
unref(mainStore).mainTarget === "chat" ? (openBlock(), createBlock(_sfc_main$j, { key: 1 })) : createCommentVNode("", true),
|
|
18582
19017
|
_cache[0] || (_cache[0] = createBaseVNode("div", { class: "util" }, null, -1))
|
|
18583
19018
|
], 2);
|
|
18584
19019
|
};
|
|
18585
19020
|
}
|
|
18586
19021
|
});
|
|
18587
|
-
const _style_0 = "[data-v-
|
|
18588
|
-
const App = /* @__PURE__ */ _export_sfc(_sfc_main, [["styles", [_style_0]], ["__scopeId", "data-v-
|
|
19022
|
+
const _style_0 = "[data-v-4f474ef7]:host{display:block;height:100%}[data-v-4f474ef7]:host,.studio-chat-root[data-v-4f474ef7]{--scm-font-size: 16px;--scm-color-primary: #008cff;--scm-color-own: #ff009d;--scm-color-surface: #f6f6f6;--scm-color-muted: #757474;--scm-color-danger: #e53935;font-family:Open Sans,sans-serif;font-size:var(--scm-font-size)}#app[data-v-4f474ef7]{height:100vh}.studio-chat-root[data-v-4f474ef7]{display:grid;grid-template-rows:40px 1fr;grid-template-columns:minmax(200px,400px) 1fr;height:100%}.studio-chat-root .header[data-v-4f474ef7]{display:grid;background-color:var(--scm-color-surface);grid-template-columns:max-content 1fr;align-content:center}.studio-chat-root.disconnected[data-v-4f474ef7]{grid-template-rows:60px 1fr}.studio-chat-root.disconnected .header[data-v-4f474ef7]{grid-template-rows:40px 20px}.studio-chat-root.disconnected .header .connection-status[data-v-4f474ef7]{grid-column:1/3}.studio-chat-root .conversations-module[data-v-4f474ef7]{grid-column:1}.studio-chat-root .chats-module[data-v-4f474ef7]{grid-column:2}.studio-chat-root.support-no-sidebar[data-v-4f474ef7]{grid-template-columns:1fr}.studio-chat-root.support-no-sidebar .chats-module[data-v-4f474ef7]{grid-column:1}.studio-chat-root.compact[data-v-4f474ef7]{grid-template-columns:1fr}.studio-chat-root.compact .chats-module[data-v-4f474ef7]{grid-column:1}.studio-chat-root.compact .main-left-target[data-v-4f474ef7]{width:100%;position:absolute;top:40px;left:0;transform:translate(-100%);transition:transform .3s ease-in-out;background-color:#fff;z-index:100;height:calc(100% - 40px)}.studio-chat-root.compact.conversations .main-left-target[data-v-4f474ef7],.studio-chat-root.compact.contacts-new .main-left-target[data-v-4f474ef7],.studio-chat-root.compact.contacts-edit .main-left-target[data-v-4f474ef7]{transform:translate(0)}.studio-chat-root.compact.disconnected .main-left-target[data-v-4f474ef7]{top:60px;height:calc(100% - 60px)}[data-v-4f474ef7],[data-v-4f474ef7]:before,[data-v-4f474ef7]:after{box-sizing:border-box;margin:0;padding:0;background-repeat:no-repeat}[data-v-4f474ef7]{min-width:0}img[data-v-4f474ef7],picture[data-v-4f474ef7],video[data-v-4f474ef7],canvas[data-v-4f474ef7],svg[data-v-4f474ef7]{display:block;max-width:100%}input[data-v-4f474ef7],button[data-v-4f474ef7],textarea[data-v-4f474ef7],select[data-v-4f474ef7]{font:inherit;color:inherit}a[data-v-4f474ef7]{text-decoration:none;color:inherit}ul[data-v-4f474ef7],ol[data-v-4f474ef7]{list-style:none}p[data-v-4f474ef7],h1[data-v-4f474ef7],h2[data-v-4f474ef7],h3[data-v-4f474ef7],h4[data-v-4f474ef7],h5[data-v-4f474ef7],h6[data-v-4f474ef7]{overflow-wrap:break-word}h1[data-v-4f474ef7],h2[data-v-4f474ef7],h3[data-v-4f474ef7],h4[data-v-4f474ef7],h5[data-v-4f474ef7],h6[data-v-4f474ef7]{font-size:inherit;font-weight:inherit}";
|
|
19023
|
+
const App = /* @__PURE__ */ _export_sfc(_sfc_main, [["styles", [_style_0]], ["__scopeId", "data-v-4f474ef7"]]);
|
|
18589
19024
|
dayjs.extend(relativeTime);
|
|
18590
19025
|
const LilaquadratStudioChat = /* @__PURE__ */ defineCustomElement(App, {
|
|
18591
19026
|
shadowRoot: true,
|