@lilaquadrat/chat 0.1.3 → 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/tsconfig.build.tsbuildinfo +1 -1
- package/dist/wc/lilaquadrat-studio-chat.js +610 -204
- package/dist/wc/lilaquadrat-studio-chat.umd.cjs +9 -9
- package/package.json +1 -1
|
@@ -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
|
);
|
|
@@ -15354,21 +15376,22 @@ const useConversationsStore = /* @__PURE__ */ defineStore("conversations", () =>
|
|
|
15354
15376
|
};
|
|
15355
15377
|
});
|
|
15356
15378
|
const _hoisted_1$e = { class: "conversations-module" };
|
|
15357
|
-
const _hoisted_2$
|
|
15379
|
+
const _hoisted_2$b = ["onClick"];
|
|
15358
15380
|
const _hoisted_3$6 = { class: "time" };
|
|
15359
|
-
const _hoisted_4$3 = {
|
|
15360
|
-
|
|
15381
|
+
const _hoisted_4$3 = { class: "message-unread-container" };
|
|
15382
|
+
const _hoisted_5$3 = {
|
|
15383
|
+
key: 0,
|
|
15361
15384
|
class: "lastMessage"
|
|
15362
15385
|
};
|
|
15363
|
-
const
|
|
15364
|
-
key:
|
|
15386
|
+
const _hoisted_6$2 = {
|
|
15387
|
+
key: 1,
|
|
15365
15388
|
class: "unread"
|
|
15366
15389
|
};
|
|
15367
|
-
const
|
|
15368
|
-
key:
|
|
15390
|
+
const _hoisted_7$2 = {
|
|
15391
|
+
key: 3,
|
|
15369
15392
|
class: "draft"
|
|
15370
15393
|
};
|
|
15371
|
-
const _sfc_main$
|
|
15394
|
+
const _sfc_main$k = /* @__PURE__ */ defineComponent({
|
|
15372
15395
|
__name: "conversations.module",
|
|
15373
15396
|
setup(__props) {
|
|
15374
15397
|
const conversationsStore = useConversationsStore();
|
|
@@ -15376,14 +15399,13 @@ const _sfc_main$j = /* @__PURE__ */ defineComponent({
|
|
|
15376
15399
|
const userStore = useUserStore();
|
|
15377
15400
|
watch(() => userStore.user, (user) => {
|
|
15378
15401
|
if (!user) return;
|
|
15402
|
+
console.log("set user");
|
|
15379
15403
|
conversationsStore.cleanConversations();
|
|
15380
15404
|
conversationsStore.getAllConversations();
|
|
15381
15405
|
}, { immediate: true });
|
|
15382
15406
|
const conversations = computed(() => {
|
|
15383
15407
|
const safeConversations = hardCopy(conversationsStore.conversations);
|
|
15384
|
-
return safeConversations.sort((a, b) => {
|
|
15385
|
-
return dayjs(a.lastMessage?.history.created).isBefore(dayjs(b.lastMessage?.history.created)) ? 1 : -1;
|
|
15386
|
-
}).map((conversation) => ({
|
|
15408
|
+
return safeConversations.sort((a, b) => dayjs(a.lastMessage?.history.created).isBefore(dayjs(b.lastMessage?.history.created)) ? 1 : -1).map((conversation) => ({
|
|
15387
15409
|
...conversation,
|
|
15388
15410
|
isActive: activeConversation.value?._id === conversation._id && conversation._id || activeConversation.value?.id === conversation.id && conversation.id
|
|
15389
15411
|
}));
|
|
@@ -15422,16 +15444,18 @@ const _sfc_main$j = /* @__PURE__ */ defineComponent({
|
|
|
15422
15444
|
"remove-user": ""
|
|
15423
15445
|
}, null, 8, ["participants"])),
|
|
15424
15446
|
createBaseVNode("span", _hoisted_3$6, toDisplayString$1(unref(dayjs)(conversation.lastMessage?.history.created).fromNow()), 1),
|
|
15425
|
-
|
|
15426
|
-
|
|
15427
|
-
|
|
15428
|
-
|
|
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);
|
|
15429
15453
|
}), 128))
|
|
15430
15454
|
]);
|
|
15431
15455
|
};
|
|
15432
15456
|
}
|
|
15433
15457
|
});
|
|
15434
|
-
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)}";
|
|
15435
15459
|
const _export_sfc = (sfc, props) => {
|
|
15436
15460
|
const target = sfc.__vccOpts || sfc;
|
|
15437
15461
|
for (const [key, val] of props) {
|
|
@@ -15439,8 +15463,8 @@ const _export_sfc = (sfc, props) => {
|
|
|
15439
15463
|
}
|
|
15440
15464
|
return target;
|
|
15441
15465
|
};
|
|
15442
|
-
const ConversationsModule = /* @__PURE__ */ _export_sfc(_sfc_main$
|
|
15443
|
-
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({
|
|
15444
15468
|
__name: "chats.module",
|
|
15445
15469
|
setup(__props) {
|
|
15446
15470
|
const conversationsStore = useConversationsStore();
|
|
@@ -15458,11 +15482,13 @@ class WebSocketManager {
|
|
|
15458
15482
|
retryCount = 0;
|
|
15459
15483
|
retryDelay = 1e3;
|
|
15460
15484
|
retryTimeoutId = null;
|
|
15485
|
+
connectTimeoutId = null;
|
|
15461
15486
|
// Number of active consumers (components/composables) holding the socket
|
|
15462
15487
|
refCount = 0;
|
|
15463
15488
|
onConnectionChange;
|
|
15464
15489
|
heartbeatIntervalId = null;
|
|
15465
15490
|
lastActivity = 0;
|
|
15491
|
+
recoveryListenersInstalled = false;
|
|
15466
15492
|
constructor() {
|
|
15467
15493
|
}
|
|
15468
15494
|
static getInstance() {
|
|
@@ -15493,12 +15519,9 @@ class WebSocketManager {
|
|
|
15493
15519
|
url,
|
|
15494
15520
|
maxRetries = 50,
|
|
15495
15521
|
maxRetryDelay = 3e4,
|
|
15496
|
-
onMessage,
|
|
15497
|
-
onOpen,
|
|
15498
|
-
onClose,
|
|
15499
|
-
onError,
|
|
15500
15522
|
heartbeatIntervalMs = 3e4,
|
|
15501
15523
|
inactivityTimeoutMs = 6e4,
|
|
15524
|
+
connectTimeoutMs = 1e4,
|
|
15502
15525
|
buildPingMessage
|
|
15503
15526
|
} = options;
|
|
15504
15527
|
this.currentOptions = {
|
|
@@ -15507,8 +15530,10 @@ class WebSocketManager {
|
|
|
15507
15530
|
maxRetryDelay,
|
|
15508
15531
|
heartbeatIntervalMs,
|
|
15509
15532
|
inactivityTimeoutMs,
|
|
15533
|
+
connectTimeoutMs,
|
|
15510
15534
|
buildPingMessage
|
|
15511
15535
|
};
|
|
15536
|
+
this.installRecoveryListeners();
|
|
15512
15537
|
if (this.socket && (this.socket.readyState === WebSocket.OPEN || this.socket.readyState === WebSocket.CONNECTING)) {
|
|
15513
15538
|
logger.websocket("WS already connecting/open; reusing existing socket");
|
|
15514
15539
|
return;
|
|
@@ -15517,33 +15542,76 @@ class WebSocketManager {
|
|
|
15517
15542
|
clearTimeout(this.retryTimeoutId);
|
|
15518
15543
|
this.retryTimeoutId = null;
|
|
15519
15544
|
}
|
|
15545
|
+
if (this.socket) this.detachHandlers(this.socket);
|
|
15520
15546
|
const ws = new WebSocket(url);
|
|
15521
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);
|
|
15522
15558
|
ws.onopen = () => {
|
|
15559
|
+
this.clearConnectTimeout();
|
|
15523
15560
|
this.retryCount = 0;
|
|
15524
15561
|
this.lastActivity = Date.now();
|
|
15525
15562
|
logger.websocket(`connected (readyState ${ws.readyState})`);
|
|
15526
15563
|
this.onConnectionChange?.(true);
|
|
15527
|
-
onOpen?.();
|
|
15564
|
+
this.currentOptions?.onOpen?.();
|
|
15528
15565
|
this.startHeartbeat();
|
|
15529
15566
|
};
|
|
15530
15567
|
ws.onmessage = (event) => {
|
|
15531
15568
|
this.lastActivity = Date.now();
|
|
15532
|
-
onMessage?.(event.data);
|
|
15569
|
+
this.currentOptions?.onMessage?.(event.data);
|
|
15533
15570
|
};
|
|
15534
15571
|
ws.onerror = (error) => {
|
|
15535
15572
|
console.error("WebSocket error:", error);
|
|
15536
|
-
onError?.(error);
|
|
15573
|
+
this.currentOptions?.onError?.(error);
|
|
15537
15574
|
};
|
|
15538
15575
|
ws.onclose = (ev) => {
|
|
15576
|
+
this.clearConnectTimeout();
|
|
15539
15577
|
this.stopHeartbeat();
|
|
15540
15578
|
const everOpened = ev.code !== 1006 || ws.readyState === WebSocket.CLOSED;
|
|
15541
15579
|
logger.websocket(`disconnected (code ${ev.code}, clean ${ev.wasClean}, everOpened ${everOpened})`);
|
|
15542
15580
|
this.onConnectionChange?.(false);
|
|
15543
|
-
onClose?.(ev);
|
|
15581
|
+
this.currentOptions?.onClose?.(ev);
|
|
15544
15582
|
if (this.refCount > 0) this.attemptReconnect();
|
|
15545
15583
|
};
|
|
15546
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
|
+
}
|
|
15547
15615
|
startHeartbeat() {
|
|
15548
15616
|
this.stopHeartbeat();
|
|
15549
15617
|
const heartbeatIntervalMs = this.currentOptions?.heartbeatIntervalMs ?? 3e4;
|
|
@@ -15623,15 +15691,18 @@ class WebSocketManager {
|
|
|
15623
15691
|
}
|
|
15624
15692
|
_teardownSocket(reason) {
|
|
15625
15693
|
this.stopHeartbeat();
|
|
15694
|
+
this.clearConnectTimeout();
|
|
15626
15695
|
if (this.retryTimeoutId) {
|
|
15627
15696
|
clearTimeout(this.retryTimeoutId);
|
|
15628
15697
|
this.retryTimeoutId = null;
|
|
15629
15698
|
}
|
|
15630
15699
|
const ws = this.socket;
|
|
15631
15700
|
this.socket = null;
|
|
15632
|
-
if (ws
|
|
15701
|
+
if (!ws) return;
|
|
15702
|
+
this.detachHandlers(ws);
|
|
15703
|
+
if (ws.readyState === WebSocket.OPEN) {
|
|
15633
15704
|
ws.close(1e3, reason);
|
|
15634
|
-
} else if (ws
|
|
15705
|
+
} else if (ws.readyState === WebSocket.CONNECTING) {
|
|
15635
15706
|
try {
|
|
15636
15707
|
ws.close();
|
|
15637
15708
|
} catch {
|
|
@@ -15642,7 +15713,6 @@ class WebSocketManager {
|
|
|
15642
15713
|
if (this.socket && this.isConnected) {
|
|
15643
15714
|
try {
|
|
15644
15715
|
this.socket.send(JSON.stringify(message));
|
|
15645
|
-
this.lastActivity = Date.now();
|
|
15646
15716
|
return true;
|
|
15647
15717
|
} catch {
|
|
15648
15718
|
return false;
|
|
@@ -15651,32 +15721,323 @@ class WebSocketManager {
|
|
|
15651
15721
|
return false;
|
|
15652
15722
|
}
|
|
15653
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());
|
|
15654
16027
|
function useWebSocket() {
|
|
15655
16028
|
const wsManager = WebSocketManager.getInstance();
|
|
15656
|
-
const mainStore = useMainStore();
|
|
15657
16029
|
wsManager.acquire();
|
|
15658
|
-
|
|
15659
|
-
|
|
15660
|
-
};
|
|
15661
|
-
const
|
|
15662
|
-
const disconnect = () => wsManager.disconnect();
|
|
15663
|
-
const reconnect = () => wsManager.reconnect();
|
|
15664
|
-
const conversationStart = (message, participants, name, id, operationMode) => wsManager.send({ type: "conversation:start", message, participants, name, id, operationMode });
|
|
15665
|
-
const conversationLastRead = (conversation, lastReadId) => wsManager.send({ type: "conversation:lastRead", conversation, lastReadId });
|
|
15666
|
-
const messageAdd = (message, conversation) => wsManager.send({ type: "message:add", message, conversation });
|
|
15667
|
-
const authenticate = (token) => wsManager.send({ type: "authenticate", token });
|
|
15668
|
-
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 });
|
|
15669
16034
|
onUnmounted(() => {
|
|
15670
16035
|
wsManager.release();
|
|
15671
16036
|
});
|
|
15672
16037
|
return {
|
|
15673
|
-
connect,
|
|
15674
|
-
disconnect,
|
|
15675
|
-
reconnect,
|
|
15676
16038
|
conversationStart,
|
|
15677
16039
|
conversationLastRead,
|
|
15678
16040
|
messageAdd,
|
|
15679
|
-
authenticate,
|
|
15680
16041
|
conversationTyping
|
|
15681
16042
|
};
|
|
15682
16043
|
}
|
|
@@ -15750,14 +16111,6 @@ function handleMessages(message) {
|
|
|
15750
16111
|
}
|
|
15751
16112
|
function setGetUsers(fn) {
|
|
15752
16113
|
}
|
|
15753
|
-
let getTokenImpl = null;
|
|
15754
|
-
function setGetToken(fn) {
|
|
15755
|
-
getTokenImpl = fn;
|
|
15756
|
-
}
|
|
15757
|
-
async function resolveToken() {
|
|
15758
|
-
if (!getTokenImpl) return void 0;
|
|
15759
|
-
return await getTokenImpl();
|
|
15760
|
-
}
|
|
15761
16114
|
function getName(name, type, namespace) {
|
|
15762
16115
|
return `${name}-${type}`;
|
|
15763
16116
|
}
|
|
@@ -16077,8 +16430,37 @@ function groupMessages(messages, user) {
|
|
|
16077
16430
|
});
|
|
16078
16431
|
return Object.values(dateGroups);
|
|
16079
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
|
+
}
|
|
16080
16462
|
const _hoisted_1$d = { class: "chat-messages" };
|
|
16081
|
-
const _hoisted_2$
|
|
16463
|
+
const _hoisted_2$a = { class: "date-separator" };
|
|
16082
16464
|
const _hoisted_3$5 = { class: "message-content" };
|
|
16083
16465
|
const _hoisted_4$2 = ["id"];
|
|
16084
16466
|
const _hoisted_5$2 = {
|
|
@@ -16087,7 +16469,7 @@ const _hoisted_5$2 = {
|
|
|
16087
16469
|
};
|
|
16088
16470
|
const SCROLL_DEBOUNCE_MS = 100;
|
|
16089
16471
|
const SCROLL_EDGE_PERCENT = 10;
|
|
16090
|
-
const _sfc_main$
|
|
16472
|
+
const _sfc_main$i = /* @__PURE__ */ defineComponent({
|
|
16091
16473
|
__name: "chat.module",
|
|
16092
16474
|
props: {
|
|
16093
16475
|
_id: { type: String },
|
|
@@ -16114,6 +16496,7 @@ const _sfc_main$h = /* @__PURE__ */ defineComponent({
|
|
|
16114
16496
|
const newChatExists = /* @__PURE__ */ ref(false);
|
|
16115
16497
|
const existingChat = /* @__PURE__ */ ref(null);
|
|
16116
16498
|
const mainStore = useMainStore();
|
|
16499
|
+
const { chatVisible } = useChatVisibility(chatMessagesRef);
|
|
16117
16500
|
let scrollDebounceTimer = null;
|
|
16118
16501
|
let typingIdleTimer = null;
|
|
16119
16502
|
let lastTypingSent = 0;
|
|
@@ -16184,12 +16567,16 @@ const _sfc_main$h = /* @__PURE__ */ defineComponent({
|
|
|
16184
16567
|
}
|
|
16185
16568
|
}
|
|
16186
16569
|
function updateLastRead() {
|
|
16570
|
+
if (!chatVisible.value) return;
|
|
16187
16571
|
if (conversation.value?.participant?.lastReadId < conversation.value?.lastMessage?.id) {
|
|
16188
16572
|
conversationLastRead(props._id, conversation.value.lastMessage.id);
|
|
16189
16573
|
conversationsStore.setLastReadId(props._id, conversation.value.lastMessage.id);
|
|
16190
16574
|
conversationsStore.updateUnread(props._id);
|
|
16191
16575
|
}
|
|
16192
16576
|
}
|
|
16577
|
+
watch(chatVisible, (visible) => {
|
|
16578
|
+
if (visible) updateLastRead();
|
|
16579
|
+
});
|
|
16193
16580
|
function scrollToBottom() {
|
|
16194
16581
|
if (chatMessagesRef.value) {
|
|
16195
16582
|
chatMessagesRef.value.scrollTop = chatMessagesRef.value.scrollHeight;
|
|
@@ -16322,7 +16709,7 @@ const _sfc_main$h = /* @__PURE__ */ defineComponent({
|
|
|
16322
16709
|
key: dateGroup.date,
|
|
16323
16710
|
class: "messages-group"
|
|
16324
16711
|
}, [
|
|
16325
|
-
createBaseVNode("div", _hoisted_2$
|
|
16712
|
+
createBaseVNode("div", _hoisted_2$a, toDisplayString$1(dateGroup.date), 1),
|
|
16326
16713
|
(openBlock(true), createElementBlock(Fragment, null, renderList(dateGroup.userTimeGroups, (group, index) => {
|
|
16327
16714
|
return openBlock(), createElementBlock("div", {
|
|
16328
16715
|
key: index,
|
|
@@ -16371,8 +16758,8 @@ const _sfc_main$h = /* @__PURE__ */ defineComponent({
|
|
|
16371
16758
|
};
|
|
16372
16759
|
}
|
|
16373
16760
|
});
|
|
16374
|
-
const _style_0$
|
|
16375
|
-
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"]]);
|
|
16376
16763
|
function sdkOptions() {
|
|
16377
16764
|
const mainStore = useMainStore();
|
|
16378
16765
|
return {
|
|
@@ -16401,7 +16788,7 @@ const useContactsStore = /* @__PURE__ */ defineStore("contacts", () => {
|
|
|
16401
16788
|
};
|
|
16402
16789
|
});
|
|
16403
16790
|
const _hoisted_1$c = { class: "contacts-module" };
|
|
16404
|
-
const _hoisted_2$
|
|
16791
|
+
const _hoisted_2$9 = {
|
|
16405
16792
|
key: 0,
|
|
16406
16793
|
class: "controls"
|
|
16407
16794
|
};
|
|
@@ -16417,7 +16804,7 @@ const _hoisted_8$1 = {
|
|
|
16417
16804
|
key: 0,
|
|
16418
16805
|
class: "selected-indicator"
|
|
16419
16806
|
};
|
|
16420
|
-
const _sfc_main$
|
|
16807
|
+
const _sfc_main$h = /* @__PURE__ */ defineComponent({
|
|
16421
16808
|
__name: "contacts.module",
|
|
16422
16809
|
setup(__props) {
|
|
16423
16810
|
const mainStore = useMainStore();
|
|
@@ -16520,7 +16907,7 @@ const _sfc_main$g = /* @__PURE__ */ defineComponent({
|
|
|
16520
16907
|
const _component_button_partial = resolveComponent("button-partial");
|
|
16521
16908
|
const _component_user_avatar_partial = resolveComponent("user-avatar-partial");
|
|
16522
16909
|
return openBlock(), createElementBlock("article", _hoisted_1$c, [
|
|
16523
|
-
isEdit.value ? (openBlock(), createElementBlock("section", _hoisted_2$
|
|
16910
|
+
isEdit.value ? (openBlock(), createElementBlock("section", _hoisted_2$9, [
|
|
16524
16911
|
createVNode(_component_button_partial, {
|
|
16525
16912
|
variant: "primary",
|
|
16526
16913
|
size: "sm",
|
|
@@ -16608,15 +16995,31 @@ const _sfc_main$g = /* @__PURE__ */ defineComponent({
|
|
|
16608
16995
|
};
|
|
16609
16996
|
}
|
|
16610
16997
|
});
|
|
16611
|
-
const _style_0$
|
|
16612
|
-
const ContactsModule = /* @__PURE__ */ _export_sfc(_sfc_main$
|
|
16613
|
-
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
|
+
});
|
|
16614
17016
|
const _sfc_main$f = /* @__PURE__ */ defineComponent({
|
|
16615
17017
|
__name: "participants.partial",
|
|
16616
17018
|
props: {
|
|
16617
17019
|
participants: { type: Array },
|
|
16618
17020
|
removeUser: { type: Boolean },
|
|
16619
|
-
isNew: { type: Boolean }
|
|
17021
|
+
isNew: { type: Boolean },
|
|
17022
|
+
inline: { type: Boolean }
|
|
16620
17023
|
},
|
|
16621
17024
|
setup(__props) {
|
|
16622
17025
|
const userStore = useUserStore();
|
|
@@ -16629,29 +17032,35 @@ const _sfc_main$f = /* @__PURE__ */ defineComponent({
|
|
|
16629
17032
|
});
|
|
16630
17033
|
return (_ctx, _cache) => {
|
|
16631
17034
|
const _component_user_avatar_partial = resolveComponent("user-avatar-partial");
|
|
16632
|
-
return openBlock(), createElementBlock("section",
|
|
17035
|
+
return openBlock(), createElementBlock("section", {
|
|
17036
|
+
class: normalizeClass(["participants-partial", { "participants-partial--inline": __props.inline }])
|
|
17037
|
+
}, [
|
|
16633
17038
|
__props.isNew && !filteredParticipants.value.length ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [
|
|
16634
17039
|
createTextVNode(toDisplayString$1(_ctx.$t("select contacts")), 1)
|
|
16635
17040
|
], 64)) : (openBlock(true), createElementBlock(Fragment, { key: 1 }, renderList(filteredParticipants.value, (participant, index) => {
|
|
16636
17041
|
return openBlock(), createElementBlock(Fragment, {
|
|
16637
17042
|
key: unref(participantId)(participant)
|
|
16638
17043
|
}, [
|
|
16639
|
-
|
|
17044
|
+
__props.inline ? (openBlock(), createBlock(_sfc_main$g, {
|
|
17045
|
+
key: 0,
|
|
17046
|
+
"user-id": unref(participantId)(participant)
|
|
17047
|
+
}, null, 8, ["user-id"])) : (openBlock(), createBlock(_component_user_avatar_partial, {
|
|
17048
|
+
key: 1,
|
|
16640
17049
|
"user-id": unref(participantId)(participant)
|
|
16641
|
-
}, null, 8, ["user-id"]),
|
|
16642
|
-
index < filteredParticipants.value.length - 1 ? (openBlock(), createElementBlock(Fragment, { key:
|
|
17050
|
+
}, null, 8, ["user-id"])),
|
|
17051
|
+
index < filteredParticipants.value.length - 1 ? (openBlock(), createElementBlock(Fragment, { key: 2 }, [
|
|
16643
17052
|
createTextVNode(toDisplayString$1(", "))
|
|
16644
17053
|
], 64)) : createCommentVNode("", true)
|
|
16645
17054
|
], 64);
|
|
16646
17055
|
}), 128))
|
|
16647
|
-
]);
|
|
17056
|
+
], 2);
|
|
16648
17057
|
};
|
|
16649
17058
|
}
|
|
16650
17059
|
});
|
|
16651
|
-
const _style_0$
|
|
16652
|
-
const ParticipantsPartial = /* @__PURE__ */ _export_sfc(_sfc_main$f, [["styles", [_style_0$
|
|
16653
|
-
const _hoisted_1$
|
|
16654
|
-
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" };
|
|
16655
17064
|
const _hoisted_3$3 = { class: "right" };
|
|
16656
17065
|
const _sfc_main$e = /* @__PURE__ */ defineComponent({
|
|
16657
17066
|
__name: "actions.partial",
|
|
@@ -16660,17 +17069,11 @@ const _sfc_main$e = /* @__PURE__ */ defineComponent({
|
|
|
16660
17069
|
const conversationsStore = useConversationsStore();
|
|
16661
17070
|
const userStore = useUserStore();
|
|
16662
17071
|
const hasChat = computed(() => mainStore.hasChat);
|
|
16663
|
-
const showConversationsButton = computed(
|
|
16664
|
-
() => hasChat.value || conversationsStore.conversations.length > 1
|
|
16665
|
-
);
|
|
16666
17072
|
const createConversation = () => {
|
|
16667
17073
|
const tempId = conversationsStore.createNew([userStore.user], userStore.user);
|
|
16668
17074
|
conversationsStore.activateConversation(tempId);
|
|
16669
|
-
mainStore.
|
|
17075
|
+
mainStore.hideLeft();
|
|
16670
17076
|
};
|
|
16671
|
-
function showConversations() {
|
|
16672
|
-
mainStore.showConversations();
|
|
16673
|
-
}
|
|
16674
17077
|
function close() {
|
|
16675
17078
|
if (mainStore.leftTarget === "contacts-edit" || mainStore.leftTarget === "contacts-new") {
|
|
16676
17079
|
mainStore.showConversations();
|
|
@@ -16679,18 +17082,13 @@ const _sfc_main$e = /* @__PURE__ */ defineComponent({
|
|
|
16679
17082
|
mainStore.closeCallback?.();
|
|
16680
17083
|
}
|
|
16681
17084
|
return (_ctx, _cache) => {
|
|
17085
|
+
const _component_conversations_button_partial = resolveComponent("conversations-button-partial");
|
|
16682
17086
|
const _component_button_partial = resolveComponent("button-partial");
|
|
16683
|
-
return openBlock(), createElementBlock("section", _hoisted_1$
|
|
16684
|
-
createBaseVNode("section", _hoisted_2$
|
|
16685
|
-
|
|
16686
|
-
key: 0,
|
|
16687
|
-
icon: "chat",
|
|
16688
|
-
variant: "secondary",
|
|
16689
|
-
"aria-label": "Conversations",
|
|
16690
|
-
onClick: showConversations
|
|
16691
|
-
})) : createCommentVNode("", true),
|
|
17087
|
+
return openBlock(), createElementBlock("section", _hoisted_1$b, [
|
|
17088
|
+
createBaseVNode("section", _hoisted_2$8, [
|
|
17089
|
+
createVNode(_component_conversations_button_partial),
|
|
16692
17090
|
hasChat.value ? (openBlock(), createBlock(_component_button_partial, {
|
|
16693
|
-
key:
|
|
17091
|
+
key: 0,
|
|
16694
17092
|
icon: "add",
|
|
16695
17093
|
"aria-label": "New chat",
|
|
16696
17094
|
onClick: createConversation
|
|
@@ -16707,10 +17105,10 @@ const _sfc_main$e = /* @__PURE__ */ defineComponent({
|
|
|
16707
17105
|
};
|
|
16708
17106
|
}
|
|
16709
17107
|
});
|
|
16710
|
-
const _style_0$
|
|
16711
|
-
const ActionsPartial = /* @__PURE__ */ _export_sfc(_sfc_main$e, [["styles", [_style_0$
|
|
16712
|
-
const _hoisted_1$
|
|
16713
|
-
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 };
|
|
16714
17112
|
const _sfc_main$d = /* @__PURE__ */ defineComponent({
|
|
16715
17113
|
__name: "chat-header.partial",
|
|
16716
17114
|
props: {
|
|
@@ -16781,7 +17179,7 @@ const _sfc_main$d = /* @__PURE__ */ defineComponent({
|
|
|
16781
17179
|
return openBlock(), createElementBlock("header", {
|
|
16782
17180
|
class: normalizeClass(["chat-header", { isSupport: isSupport.value }])
|
|
16783
17181
|
}, [
|
|
16784
|
-
createBaseVNode("section", _hoisted_1$
|
|
17182
|
+
createBaseVNode("section", _hoisted_1$a, [
|
|
16785
17183
|
createBaseVNode("h3", null, [
|
|
16786
17184
|
!isSupport.value ? (openBlock(), createBlock(_component_name_edit_partial, {
|
|
16787
17185
|
key: 0,
|
|
@@ -16796,9 +17194,10 @@ const _sfc_main$d = /* @__PURE__ */ defineComponent({
|
|
|
16796
17194
|
createTextVNode(toDisplayString$1(_ctx.$t("support")), 1)
|
|
16797
17195
|
], 64)) : createCommentVNode("", true)
|
|
16798
17196
|
]),
|
|
16799
|
-
!isSupport.value && conversationData.value ? (openBlock(), createElementBlock("h4", _hoisted_2$
|
|
17197
|
+
!isSupport.value && conversationData.value ? (openBlock(), createElementBlock("h4", _hoisted_2$7, [
|
|
16800
17198
|
createVNode(_component_participants_partial, {
|
|
16801
17199
|
participants: conversationData.value.participants,
|
|
17200
|
+
inline: "",
|
|
16802
17201
|
"remove-user": "",
|
|
16803
17202
|
"is-new": isNew.value
|
|
16804
17203
|
}, null, 8, ["participants", "is-new"]),
|
|
@@ -16806,13 +17205,9 @@ const _sfc_main$d = /* @__PURE__ */ defineComponent({
|
|
|
16806
17205
|
key: 0,
|
|
16807
17206
|
size: "sm",
|
|
16808
17207
|
variant: "ghost",
|
|
17208
|
+
icon: "edit",
|
|
16809
17209
|
"aria-label": "Toggle edit mode",
|
|
16810
17210
|
onClick: _cache[0] || (_cache[0] = ($event) => toggleEdit())
|
|
16811
|
-
}, {
|
|
16812
|
-
default: withCtx(() => [..._cache[1] || (_cache[1] = [
|
|
16813
|
-
createTextVNode(" edit ", -1)
|
|
16814
|
-
])]),
|
|
16815
|
-
_: 1
|
|
16816
17211
|
})) : createCommentVNode("", true)
|
|
16817
17212
|
])) : createCommentVNode("", true),
|
|
16818
17213
|
!isSupport.value && !isNew.value ? (openBlock(), createBlock(_component_chat_actions_partial, {
|
|
@@ -16824,8 +17219,8 @@ const _sfc_main$d = /* @__PURE__ */ defineComponent({
|
|
|
16824
17219
|
};
|
|
16825
17220
|
}
|
|
16826
17221
|
});
|
|
16827
|
-
const _style_0$
|
|
16828
|
-
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"]]);
|
|
16829
17224
|
const _sfc_main$c = /* @__PURE__ */ defineComponent({
|
|
16830
17225
|
__name: "name-edit.partial",
|
|
16831
17226
|
props: {
|
|
@@ -16869,17 +17264,13 @@ const _sfc_main$c = /* @__PURE__ */ defineComponent({
|
|
|
16869
17264
|
return openBlock(), createElementBlock(Fragment, null, [
|
|
16870
17265
|
!edit.value ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [
|
|
16871
17266
|
renderSlot(_ctx.$slots, "default"),
|
|
16872
|
-
_cache[
|
|
17267
|
+
_cache[1] || (_cache[1] = createTextVNode()),
|
|
16873
17268
|
createVNode(_component_button_partial, {
|
|
16874
17269
|
size: "sm",
|
|
16875
17270
|
variant: "ghost",
|
|
17271
|
+
icon: "edit",
|
|
16876
17272
|
"aria-label": "Edit conversation name",
|
|
16877
17273
|
onClick: toggleEdit
|
|
16878
|
-
}, {
|
|
16879
|
-
default: withCtx(() => [..._cache[1] || (_cache[1] = [
|
|
16880
|
-
createTextVNode(" Edit ", -1)
|
|
16881
|
-
])]),
|
|
16882
|
-
_: 1
|
|
16883
17274
|
})
|
|
16884
17275
|
], 64)) : createCommentVNode("", true),
|
|
16885
17276
|
edit.value ? (openBlock(), createElementBlock(Fragment, { key: 1 }, [
|
|
@@ -16899,7 +17290,7 @@ const _sfc_main$c = /* @__PURE__ */ defineComponent({
|
|
|
16899
17290
|
disabled: !name.value?.length,
|
|
16900
17291
|
onClick: save
|
|
16901
17292
|
}, {
|
|
16902
|
-
default: withCtx(() => [..._cache[
|
|
17293
|
+
default: withCtx(() => [..._cache[2] || (_cache[2] = [
|
|
16903
17294
|
createTextVNode(" Save ", -1)
|
|
16904
17295
|
])]),
|
|
16905
17296
|
_: 1
|
|
@@ -16910,7 +17301,7 @@ const _sfc_main$c = /* @__PURE__ */ defineComponent({
|
|
|
16910
17301
|
"aria-label": "Cancel editing",
|
|
16911
17302
|
onClick: toggleEdit
|
|
16912
17303
|
}, {
|
|
16913
|
-
default: withCtx(() => [..._cache[
|
|
17304
|
+
default: withCtx(() => [..._cache[3] || (_cache[3] = [
|
|
16914
17305
|
createTextVNode(" X ", -1)
|
|
16915
17306
|
])]),
|
|
16916
17307
|
_: 1
|
|
@@ -16920,7 +17311,7 @@ const _sfc_main$c = /* @__PURE__ */ defineComponent({
|
|
|
16920
17311
|
};
|
|
16921
17312
|
}
|
|
16922
17313
|
});
|
|
16923
|
-
const _hoisted_1$
|
|
17314
|
+
const _hoisted_1$9 = { class: "notice-partial" };
|
|
16924
17315
|
const _sfc_main$b = /* @__PURE__ */ defineComponent({
|
|
16925
17316
|
__name: "notice.partial",
|
|
16926
17317
|
props: {
|
|
@@ -16928,14 +17319,14 @@ const _sfc_main$b = /* @__PURE__ */ defineComponent({
|
|
|
16928
17319
|
},
|
|
16929
17320
|
setup(__props) {
|
|
16930
17321
|
return (_ctx, _cache) => {
|
|
16931
|
-
return openBlock(), createElementBlock("section", _hoisted_1$
|
|
17322
|
+
return openBlock(), createElementBlock("section", _hoisted_1$9, [
|
|
16932
17323
|
renderSlot(_ctx.$slots, "default", {}, void 0, true)
|
|
16933
17324
|
]);
|
|
16934
17325
|
};
|
|
16935
17326
|
}
|
|
16936
17327
|
});
|
|
16937
|
-
const _style_0$
|
|
16938
|
-
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"]]);
|
|
16939
17330
|
const _sfc_main$a = /* @__PURE__ */ defineComponent({
|
|
16940
17331
|
...{ inheritAttrs: false },
|
|
16941
17332
|
__name: "system-message.partial",
|
|
@@ -16979,8 +17370,8 @@ const _sfc_main$a = /* @__PURE__ */ defineComponent({
|
|
|
16979
17370
|
};
|
|
16980
17371
|
}
|
|
16981
17372
|
});
|
|
16982
|
-
const _hoisted_1$
|
|
16983
|
-
const _hoisted_2$
|
|
17373
|
+
const _hoisted_1$8 = { class: "chat-actions-partial" };
|
|
17374
|
+
const _hoisted_2$6 = { class: "options-container" };
|
|
16984
17375
|
const _sfc_main$9 = /* @__PURE__ */ defineComponent({
|
|
16985
17376
|
__name: "chat-actions.partial",
|
|
16986
17377
|
props: {
|
|
@@ -17011,7 +17402,7 @@ const _sfc_main$9 = /* @__PURE__ */ defineComponent({
|
|
|
17011
17402
|
const _component_button_partial = resolveComponent("button-partial");
|
|
17012
17403
|
const _component_overlay_container_partial = resolveComponent("overlay-container-partial");
|
|
17013
17404
|
const _component_dialog_partial = resolveComponent("dialog-partial");
|
|
17014
|
-
return openBlock(), createElementBlock("section", _hoisted_1$
|
|
17405
|
+
return openBlock(), createElementBlock("section", _hoisted_1$8, [
|
|
17015
17406
|
createVNode(_component_button_partial, {
|
|
17016
17407
|
ref_key: "attachTo",
|
|
17017
17408
|
ref: attachTo,
|
|
@@ -17031,7 +17422,7 @@ const _sfc_main$9 = /* @__PURE__ */ defineComponent({
|
|
|
17031
17422
|
onClose: toggle
|
|
17032
17423
|
}, {
|
|
17033
17424
|
default: withCtx(() => [
|
|
17034
|
-
createBaseVNode("section", _hoisted_2$
|
|
17425
|
+
createBaseVNode("section", _hoisted_2$6, [
|
|
17035
17426
|
createBaseVNode("ul", null, [
|
|
17036
17427
|
createBaseVNode("li", null, toDisplayString$1(_ctx.$t("mute")), 1),
|
|
17037
17428
|
createBaseVNode("li", null, toDisplayString$1(_ctx.$t("delete")), 1),
|
|
@@ -17072,8 +17463,8 @@ const _sfc_main$9 = /* @__PURE__ */ defineComponent({
|
|
|
17072
17463
|
};
|
|
17073
17464
|
}
|
|
17074
17465
|
});
|
|
17075
|
-
const _style_0$
|
|
17076
|
-
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"]]);
|
|
17077
17468
|
const _sfc_main$8 = /* @__PURE__ */ defineComponent({
|
|
17078
17469
|
__name: "overlay-container.partial",
|
|
17079
17470
|
props: {
|
|
@@ -17208,10 +17599,10 @@ const _sfc_main$8 = /* @__PURE__ */ defineComponent({
|
|
|
17208
17599
|
};
|
|
17209
17600
|
}
|
|
17210
17601
|
});
|
|
17211
|
-
const _style_0$
|
|
17212
|
-
const OverlayContainerPartial = /* @__PURE__ */ _export_sfc(_sfc_main$8, [["styles", [_style_0$
|
|
17213
|
-
const _hoisted_1$
|
|
17214
|
-
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 = {
|
|
17215
17606
|
key: 0,
|
|
17216
17607
|
class: "scm-btn__spinner",
|
|
17217
17608
|
"aria-hidden": "true"
|
|
@@ -17264,19 +17655,19 @@ const _sfc_main$7 = /* @__PURE__ */ defineComponent({
|
|
|
17264
17655
|
class: normalizeClass(classes.value),
|
|
17265
17656
|
onClick
|
|
17266
17657
|
}, [
|
|
17267
|
-
props.loading ? (openBlock(), createElementBlock("span", _hoisted_2$
|
|
17658
|
+
props.loading ? (openBlock(), createElementBlock("span", _hoisted_2$5)) : props.icon ? (openBlock(), createBlock(_component_icons_partial, {
|
|
17268
17659
|
key: 1,
|
|
17269
17660
|
type: props.icon
|
|
17270
17661
|
}, null, 8, ["type"])) : (openBlock(), createElementBlock("span", _hoisted_3$2, [
|
|
17271
17662
|
renderSlot(_ctx.$slots, "default", {}, void 0, true)
|
|
17272
17663
|
]))
|
|
17273
|
-
], 10, _hoisted_1$
|
|
17664
|
+
], 10, _hoisted_1$7);
|
|
17274
17665
|
};
|
|
17275
17666
|
}
|
|
17276
17667
|
});
|
|
17277
|
-
const _style_0$
|
|
17278
|
-
const ButtonPartial = /* @__PURE__ */ _export_sfc(_sfc_main$7, [["styles", [_style_0$
|
|
17279
|
-
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" };
|
|
17280
17671
|
const _sfc_main$6 = /* @__PURE__ */ defineComponent({
|
|
17281
17672
|
__name: "dialog.partial",
|
|
17282
17673
|
emits: ["accept", "decline"],
|
|
@@ -17290,7 +17681,7 @@ const _sfc_main$6 = /* @__PURE__ */ defineComponent({
|
|
|
17290
17681
|
}
|
|
17291
17682
|
return (_ctx, _cache) => {
|
|
17292
17683
|
const _component_button_partial = resolveComponent("button-partial");
|
|
17293
|
-
return openBlock(), createElementBlock("section", _hoisted_1$
|
|
17684
|
+
return openBlock(), createElementBlock("section", _hoisted_1$6, [
|
|
17294
17685
|
renderSlot(_ctx.$slots, "default", {}, void 0, true),
|
|
17295
17686
|
createVNode(_component_button_partial, { onClick: onAccept }, {
|
|
17296
17687
|
default: withCtx(() => [..._cache[0] || (_cache[0] = [
|
|
@@ -17308,10 +17699,10 @@ const _sfc_main$6 = /* @__PURE__ */ defineComponent({
|
|
|
17308
17699
|
};
|
|
17309
17700
|
}
|
|
17310
17701
|
});
|
|
17311
|
-
const _style_0$
|
|
17312
|
-
const DialogPartial = /* @__PURE__ */ _export_sfc(_sfc_main$6, [["styles", [_style_0$
|
|
17313
|
-
const _hoisted_1$
|
|
17314
|
-
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" };
|
|
17315
17706
|
const _hoisted_3$1 = ["value", "placeholder"];
|
|
17316
17707
|
const _sfc_main$5 = /* @__PURE__ */ defineComponent({
|
|
17317
17708
|
__name: "chat-input.partial",
|
|
@@ -17346,8 +17737,8 @@ const _sfc_main$5 = /* @__PURE__ */ defineComponent({
|
|
|
17346
17737
|
watch(() => props.modelValue, () => nextTick(resize2));
|
|
17347
17738
|
return (_ctx, _cache) => {
|
|
17348
17739
|
const _component_button_partial = resolveComponent("button-partial");
|
|
17349
|
-
return openBlock(), createElementBlock("div", _hoisted_1$
|
|
17350
|
-
createBaseVNode("section", _hoisted_2$
|
|
17740
|
+
return openBlock(), createElementBlock("div", _hoisted_1$5, [
|
|
17741
|
+
createBaseVNode("section", _hoisted_2$4, [
|
|
17351
17742
|
createBaseVNode("textarea", {
|
|
17352
17743
|
ref_key: "textareaRef",
|
|
17353
17744
|
ref: textareaRef,
|
|
@@ -17369,26 +17760,10 @@ const _sfc_main$5 = /* @__PURE__ */ defineComponent({
|
|
|
17369
17760
|
};
|
|
17370
17761
|
}
|
|
17371
17762
|
});
|
|
17372
|
-
const _style_0$
|
|
17373
|
-
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" };
|
|
17374
17766
|
const _sfc_main$4 = /* @__PURE__ */ defineComponent({
|
|
17375
|
-
__name: "user-name.partial",
|
|
17376
|
-
props: {
|
|
17377
|
-
userId: { type: String }
|
|
17378
|
-
},
|
|
17379
|
-
setup(__props) {
|
|
17380
|
-
const props = __props;
|
|
17381
|
-
const usersCache = useUsersCacheStore();
|
|
17382
|
-
onMounted(() => {
|
|
17383
|
-
usersCache.ensure([props.userId]);
|
|
17384
|
-
});
|
|
17385
|
-
return (_ctx, _cache) => {
|
|
17386
|
-
return toDisplayString$1(unref(usersCache).name(props.userId));
|
|
17387
|
-
};
|
|
17388
|
-
}
|
|
17389
|
-
});
|
|
17390
|
-
const _hoisted_1$3 = { class: "user-avatar" };
|
|
17391
|
-
const _sfc_main$3 = /* @__PURE__ */ defineComponent({
|
|
17392
17767
|
__name: "user-avatar.partial",
|
|
17393
17768
|
props: {
|
|
17394
17769
|
userId: { type: String }
|
|
@@ -17413,19 +17788,19 @@ const _sfc_main$3 = /* @__PURE__ */ defineComponent({
|
|
|
17413
17788
|
usersCache.ensure([props.userId]);
|
|
17414
17789
|
});
|
|
17415
17790
|
return (_ctx, _cache) => {
|
|
17416
|
-
return openBlock(), createElementBlock("span", _hoisted_1$
|
|
17791
|
+
return openBlock(), createElementBlock("span", _hoisted_1$4, [
|
|
17417
17792
|
createBaseVNode("span", {
|
|
17418
17793
|
class: "user-avatar__circle",
|
|
17419
17794
|
style: normalizeStyle({ backgroundColor: `hsl(${hue.value}, 45%, 60%)` })
|
|
17420
17795
|
}, toDisplayString$1(initials.value), 5),
|
|
17421
|
-
createVNode(_sfc_main$
|
|
17796
|
+
createVNode(_sfc_main$g, { "user-id": __props.userId }, null, 8, ["user-id"])
|
|
17422
17797
|
]);
|
|
17423
17798
|
};
|
|
17424
17799
|
}
|
|
17425
17800
|
});
|
|
17426
|
-
const _style_0$
|
|
17427
|
-
const UserAvatarPartial = /* @__PURE__ */ _export_sfc(_sfc_main$
|
|
17428
|
-
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 = {
|
|
17429
17804
|
key: 0,
|
|
17430
17805
|
xmlns: "http://www.w3.org/2000/svg",
|
|
17431
17806
|
class: "h-6 w-6",
|
|
@@ -17434,7 +17809,7 @@ const _hoisted_1$2 = {
|
|
|
17434
17809
|
stroke: "currentColor",
|
|
17435
17810
|
"stroke-width": "2"
|
|
17436
17811
|
};
|
|
17437
|
-
const _hoisted_2$
|
|
17812
|
+
const _hoisted_2$3 = {
|
|
17438
17813
|
key: 1,
|
|
17439
17814
|
xmlns: "http://www.w3.org/2000/svg",
|
|
17440
17815
|
class: "h-6 w-6",
|
|
@@ -17896,7 +18271,7 @@ const _hoisted_53 = {
|
|
|
17896
18271
|
stroke: "currentColor",
|
|
17897
18272
|
class: "size-6"
|
|
17898
18273
|
};
|
|
17899
|
-
const _sfc_main$
|
|
18274
|
+
const _sfc_main$3 = /* @__PURE__ */ defineComponent({
|
|
17900
18275
|
__name: "icons.partial",
|
|
17901
18276
|
props: {
|
|
17902
18277
|
type: { type: String },
|
|
@@ -17915,14 +18290,14 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
|
|
|
17915
18290
|
return openBlock(), createElementBlock("span", {
|
|
17916
18291
|
class: normalizeClass(["icon-partial", [__props.type, __props.colorScheme || "colorScheme1", __props.size || "medium", rotateClass.value, { animate: __props.animate }]])
|
|
17917
18292
|
}, [
|
|
17918
|
-
__props.type === "arrow-right" ? (openBlock(), createElementBlock("svg", _hoisted_1$
|
|
18293
|
+
__props.type === "arrow-right" ? (openBlock(), createElementBlock("svg", _hoisted_1$3, [..._cache[0] || (_cache[0] = [
|
|
17919
18294
|
createBaseVNode("path", {
|
|
17920
18295
|
"stroke-linecap": "round",
|
|
17921
18296
|
"stroke-linejoin": "round",
|
|
17922
18297
|
d: "M9 5l7 7-7 7"
|
|
17923
18298
|
}, null, -1)
|
|
17924
18299
|
])])) : createCommentVNode("", true),
|
|
17925
|
-
__props.type === "arrow-left" ? (openBlock(), createElementBlock("svg", _hoisted_2$
|
|
18300
|
+
__props.type === "arrow-left" ? (openBlock(), createElementBlock("svg", _hoisted_2$3, [..._cache[1] || (_cache[1] = [
|
|
17926
18301
|
createBaseVNode("path", {
|
|
17927
18302
|
"stroke-linecap": "round",
|
|
17928
18303
|
"stroke-linejoin": "round",
|
|
@@ -18314,24 +18689,58 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
|
|
|
18314
18689
|
};
|
|
18315
18690
|
}
|
|
18316
18691
|
});
|
|
18317
|
-
const _style_0$
|
|
18318
|
-
const IconsPartial = /* @__PURE__ */ _export_sfc(_sfc_main$
|
|
18319
|
-
const _hoisted_1$
|
|
18320
|
-
const _hoisted_2$
|
|
18321
|
-
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({
|
|
18322
18697
|
__name: "connection-status.partial",
|
|
18323
18698
|
setup(__props) {
|
|
18324
18699
|
const mainStore = useMainStore();
|
|
18325
18700
|
const connection = computed(() => mainStore.state);
|
|
18326
18701
|
return (_ctx, _cache) => {
|
|
18327
|
-
return openBlock(), createElementBlock("section", _hoisted_1$
|
|
18328
|
-
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)
|
|
18329
18704
|
]);
|
|
18330
18705
|
};
|
|
18331
18706
|
}
|
|
18332
18707
|
});
|
|
18333
|
-
const _style_0$
|
|
18334
|
-
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"]]);
|
|
18335
18744
|
function resolveFeatures(config) {
|
|
18336
18745
|
if (config.features?.length) return [...new Set(config.features)];
|
|
18337
18746
|
switch (config.mode) {
|
|
@@ -18364,7 +18773,7 @@ function applyConfig(config, pinia) {
|
|
|
18364
18773
|
const MODULES = [
|
|
18365
18774
|
{ name: "chat", component: ChatModule },
|
|
18366
18775
|
{ name: "conversations", component: ConversationsModule },
|
|
18367
|
-
{ name: "chats", component: _sfc_main$
|
|
18776
|
+
{ name: "chats", component: _sfc_main$j },
|
|
18368
18777
|
{ name: "contacts", component: ContactsModule }
|
|
18369
18778
|
];
|
|
18370
18779
|
const PARTIALS = [
|
|
@@ -18380,9 +18789,10 @@ const PARTIALS = [
|
|
|
18380
18789
|
{ name: "dialog", component: DialogPartial },
|
|
18381
18790
|
{ name: "chat-input", component: ChatInputPartial },
|
|
18382
18791
|
{ name: "user-avatar", component: UserAvatarPartial },
|
|
18383
|
-
{ name: "user-name", component: _sfc_main$
|
|
18792
|
+
{ name: "user-name", component: _sfc_main$g },
|
|
18384
18793
|
{ name: "icons", component: IconsPartial },
|
|
18385
|
-
{ name: "connection-status", component: ConnectionStatusPartial }
|
|
18794
|
+
{ name: "connection-status", component: ConnectionStatusPartial },
|
|
18795
|
+
{ name: "conversations-button", component: ConversationsButtonPartial }
|
|
18386
18796
|
];
|
|
18387
18797
|
function registerComponents(app) {
|
|
18388
18798
|
loadViaDeclarationSync(MODULES, void 0, "module", app);
|
|
@@ -18517,10 +18927,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
18517
18927
|
const mainStore = useMainStore();
|
|
18518
18928
|
const userStore = useUserStore();
|
|
18519
18929
|
const conversationsStore = useConversationsStore();
|
|
18520
|
-
|
|
18521
|
-
connect,
|
|
18522
|
-
authenticate
|
|
18523
|
-
} = useWebSocket();
|
|
18930
|
+
useWebSocket();
|
|
18524
18931
|
const realWidth = useResize().realWidth;
|
|
18525
18932
|
const viewMode = computed(() => mainStore.viewMode);
|
|
18526
18933
|
const leftTarget = computed(() => mainStore.leftTarget);
|
|
@@ -18536,14 +18943,6 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
18536
18943
|
unreadConversations: conversationsStore.totalUnreadConversations
|
|
18537
18944
|
});
|
|
18538
18945
|
});
|
|
18539
|
-
let wasDisconnected = false;
|
|
18540
|
-
watch(() => mainStore.state, (state) => {
|
|
18541
|
-
if (state === "connected" && wasDisconnected) {
|
|
18542
|
-
conversationsStore.handleReconnect().catch((_error) => {
|
|
18543
|
-
});
|
|
18544
|
-
}
|
|
18545
|
-
wasDisconnected = state === "disconnected";
|
|
18546
|
-
});
|
|
18547
18946
|
function decodeSub(token) {
|
|
18548
18947
|
if (!token) return void 0;
|
|
18549
18948
|
try {
|
|
@@ -18571,8 +18970,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
18571
18970
|
if (props.config) applyConfig(props.config);
|
|
18572
18971
|
const token = await resolveToken() ?? props.config?.token ?? mainStore.authToken;
|
|
18573
18972
|
if (token) mainStore.authToken = token;
|
|
18574
|
-
const
|
|
18575
|
-
const userId = decodeSub(token) ?? props.config?.userId ?? userStore.user ?? urlUser;
|
|
18973
|
+
const userId = decodeSub(token) ?? props.config?.userId ?? userStore.user;
|
|
18576
18974
|
if (!userId) {
|
|
18577
18975
|
if (props.config) console.warn("[studio-chat] config has no usable identity (getToken/token sub or userId)");
|
|
18578
18976
|
return;
|
|
@@ -18580,13 +18978,19 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
18580
18978
|
started = true;
|
|
18581
18979
|
userStore.user = userId;
|
|
18582
18980
|
if (props.config?.user) useUsersCacheStore().setOne({ ...props.config.user, id: userId });
|
|
18583
|
-
|
|
18981
|
+
chatSession.start({
|
|
18584
18982
|
url: mainStore.wsUrl,
|
|
18585
|
-
|
|
18586
|
-
|
|
18587
|
-
|
|
18588
|
-
|
|
18589
|
-
|
|
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
|
+
}
|
|
18590
18994
|
});
|
|
18591
18995
|
if (mainStore.isSupportOnly) bootstrapSupport();
|
|
18592
18996
|
} finally {
|
|
@@ -18596,25 +19000,27 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
18596
19000
|
watch(() => props.config, start, { immediate: true });
|
|
18597
19001
|
return (_ctx, _cache) => {
|
|
18598
19002
|
const _component_actions_partial = resolveComponent("actions-partial");
|
|
19003
|
+
const _component_connection_status_partial = resolveComponent("connection-status-partial");
|
|
18599
19004
|
const _component_contacts_module = resolveComponent("contacts-module");
|
|
18600
19005
|
return openBlock(), createElementBlock("div", {
|
|
18601
|
-
class: normalizeClass(["studio-chat-root", [viewMode.value, leftTarget.value]])
|
|
19006
|
+
class: normalizeClass(["studio-chat-root", [viewMode.value, leftTarget.value, unref(mainStore).state]])
|
|
18602
19007
|
}, [
|
|
18603
19008
|
createBaseVNode("section", _hoisted_1, [
|
|
18604
|
-
createVNode(_component_actions_partial)
|
|
19009
|
+
createVNode(_component_actions_partial),
|
|
19010
|
+
unref(mainStore).state === "disconnected" ? (openBlock(), createBlock(_component_connection_status_partial, { key: 0 })) : createCommentVNode("", true)
|
|
18605
19011
|
]),
|
|
18606
19012
|
unref(mainStore).leftTarget ? (openBlock(), createElementBlock("section", _hoisted_2, [
|
|
18607
19013
|
unref(mainStore).leftTarget === "conversations" ? (openBlock(), createBlock(ConversationsModule, { key: 0 })) : createCommentVNode("", true),
|
|
18608
19014
|
unref(mainStore).leftTarget === "contacts-new" || unref(mainStore).leftTarget === "contacts-edit" ? (openBlock(), createBlock(_component_contacts_module, { key: 1 })) : createCommentVNode("", true)
|
|
18609
19015
|
])) : createCommentVNode("", true),
|
|
18610
|
-
unref(mainStore).mainTarget === "chat" ? (openBlock(), createBlock(_sfc_main$
|
|
19016
|
+
unref(mainStore).mainTarget === "chat" ? (openBlock(), createBlock(_sfc_main$j, { key: 1 })) : createCommentVNode("", true),
|
|
18611
19017
|
_cache[0] || (_cache[0] = createBaseVNode("div", { class: "util" }, null, -1))
|
|
18612
19018
|
], 2);
|
|
18613
19019
|
};
|
|
18614
19020
|
}
|
|
18615
19021
|
});
|
|
18616
|
-
const _style_0 = "[data-v-
|
|
18617
|
-
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"]]);
|
|
18618
19024
|
dayjs.extend(relativeTime);
|
|
18619
19025
|
const LilaquadratStudioChat = /* @__PURE__ */ defineCustomElement(App, {
|
|
18620
19026
|
shadowRoot: true,
|