hermes-chat-react 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/{chunk-OMLFDWYU.js → chunk-6L73MEPH.js} +16 -2
- package/dist/chunk-6L73MEPH.js.map +1 -0
- package/dist/cli.cjs +87 -0
- package/dist/cli.cjs.map +1 -0
- package/dist/cli.d.cts +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +64 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.cjs +15 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +1 -1
- package/dist/react.cjs +1763 -522
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +624 -22
- package/dist/react.d.ts +624 -22
- package/dist/react.js +1657 -463
- package/dist/react.js.map +1 -1
- package/package.json +13 -3
- package/dist/chunk-OMLFDWYU.js.map +0 -1
package/dist/react.js
CHANGED
|
@@ -1,6 +1,117 @@
|
|
|
1
1
|
import {
|
|
2
2
|
HermesClient
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-6L73MEPH.js";
|
|
4
|
+
|
|
5
|
+
// src/react/context/ChatContext.tsx
|
|
6
|
+
import { createContext, useContext } from "react";
|
|
7
|
+
import { jsx } from "react/jsx-runtime";
|
|
8
|
+
var ChatContext = createContext(
|
|
9
|
+
void 0
|
|
10
|
+
);
|
|
11
|
+
var ChatProvider = ({
|
|
12
|
+
children,
|
|
13
|
+
value
|
|
14
|
+
}) => /* @__PURE__ */ jsx(ChatContext.Provider, { value, children });
|
|
15
|
+
var useChatContext = (componentName) => {
|
|
16
|
+
const contextValue = useContext(ChatContext);
|
|
17
|
+
if (!contextValue) {
|
|
18
|
+
console.warn(
|
|
19
|
+
`useChatContext was called outside of ChatProvider. Make sure this hook is called within a child of the <Chat> component.${componentName ? ` Errored in: ${componentName}` : ""}`
|
|
20
|
+
);
|
|
21
|
+
return {};
|
|
22
|
+
}
|
|
23
|
+
return contextValue;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
// src/react/context/RoomStateContext.tsx
|
|
27
|
+
import { createContext as createContext2, useContext as useContext2 } from "react";
|
|
28
|
+
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
29
|
+
var RoomStateContext = createContext2(void 0);
|
|
30
|
+
var RoomStateProvider = ({
|
|
31
|
+
children,
|
|
32
|
+
value
|
|
33
|
+
}) => /* @__PURE__ */ jsx2(RoomStateContext.Provider, { value, children });
|
|
34
|
+
var useRoomStateContext = (componentName) => {
|
|
35
|
+
const contextValue = useContext2(RoomStateContext);
|
|
36
|
+
if (!contextValue) {
|
|
37
|
+
console.warn(
|
|
38
|
+
`useRoomStateContext was called outside of RoomStateProvider. Make sure this hook is called within a child of the <Room> component.${componentName ? ` Errored in: ${componentName}` : ""}`
|
|
39
|
+
);
|
|
40
|
+
return {};
|
|
41
|
+
}
|
|
42
|
+
return contextValue;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
// src/react/context/RoomActionContext.tsx
|
|
46
|
+
import { createContext as createContext3, useContext as useContext3 } from "react";
|
|
47
|
+
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
48
|
+
var RoomActionContext = createContext3(void 0);
|
|
49
|
+
var RoomActionProvider = ({
|
|
50
|
+
children,
|
|
51
|
+
value
|
|
52
|
+
}) => /* @__PURE__ */ jsx3(RoomActionContext.Provider, { value, children });
|
|
53
|
+
var useRoomActionContext = (componentName) => {
|
|
54
|
+
const contextValue = useContext3(RoomActionContext);
|
|
55
|
+
if (!contextValue) {
|
|
56
|
+
console.warn(
|
|
57
|
+
`useRoomActionContext was called outside of RoomActionProvider. Make sure this hook is called within a child of the <Room> component.${componentName ? ` Errored in: ${componentName}` : ""}`
|
|
58
|
+
);
|
|
59
|
+
return {};
|
|
60
|
+
}
|
|
61
|
+
return contextValue;
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
// src/react/context/MessageContext.tsx
|
|
65
|
+
import { createContext as createContext4, useContext as useContext4 } from "react";
|
|
66
|
+
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
67
|
+
var MessageContext = createContext4(
|
|
68
|
+
void 0
|
|
69
|
+
);
|
|
70
|
+
var MessageProvider = ({
|
|
71
|
+
children,
|
|
72
|
+
value
|
|
73
|
+
}) => /* @__PURE__ */ jsx4(MessageContext.Provider, { value, children });
|
|
74
|
+
var useMessageContext = (componentName) => {
|
|
75
|
+
const contextValue = useContext4(MessageContext);
|
|
76
|
+
if (!contextValue) {
|
|
77
|
+
console.warn(
|
|
78
|
+
`useMessageContext was called outside of MessageProvider.${componentName ? ` Errored in: ${componentName}` : ""}`
|
|
79
|
+
);
|
|
80
|
+
return {};
|
|
81
|
+
}
|
|
82
|
+
return contextValue;
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
// src/react/context/ComponentContext.tsx
|
|
86
|
+
import { createContext as createContext5, useContext as useContext5 } from "react";
|
|
87
|
+
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
88
|
+
var ComponentContext = createContext5({});
|
|
89
|
+
var ComponentProvider = ({
|
|
90
|
+
children,
|
|
91
|
+
value
|
|
92
|
+
}) => /* @__PURE__ */ jsx5(ComponentContext.Provider, { value, children });
|
|
93
|
+
var useComponentContext = (_componentName) => useContext5(ComponentContext);
|
|
94
|
+
|
|
95
|
+
// src/react/context/TypingContext.tsx
|
|
96
|
+
import { createContext as createContext6, useContext as useContext6 } from "react";
|
|
97
|
+
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
98
|
+
var TypingContext = createContext6(
|
|
99
|
+
void 0
|
|
100
|
+
);
|
|
101
|
+
var TypingProvider = ({
|
|
102
|
+
children,
|
|
103
|
+
value
|
|
104
|
+
}) => /* @__PURE__ */ jsx6(TypingContext.Provider, { value, children });
|
|
105
|
+
var useTypingContext = (componentName) => {
|
|
106
|
+
const contextValue = useContext6(TypingContext);
|
|
107
|
+
if (!contextValue) {
|
|
108
|
+
console.warn(
|
|
109
|
+
`useTypingContext was called outside of TypingProvider.${componentName ? ` Errored in: ${componentName}` : ""}`
|
|
110
|
+
);
|
|
111
|
+
return {};
|
|
112
|
+
}
|
|
113
|
+
return contextValue;
|
|
114
|
+
};
|
|
4
115
|
|
|
5
116
|
// src/react/hooks/useMessages.ts
|
|
6
117
|
import { useState, useEffect, useCallback, useRef } from "react";
|
|
@@ -544,152 +655,617 @@ var useUpload = (client) => {
|
|
|
544
655
|
return { upload, sendFile, validate, uploading, error, lastUpload };
|
|
545
656
|
};
|
|
546
657
|
|
|
547
|
-
// src/react/components/
|
|
548
|
-
import {
|
|
549
|
-
import {
|
|
550
|
-
var
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
"\u{1FAF6}",
|
|
563
|
-
"\u{1F480}",
|
|
564
|
-
"\u{1F525}",
|
|
565
|
-
"\u2728",
|
|
566
|
-
"\u{1FAE3}",
|
|
567
|
-
"\u{1F62E}\u200D\u{1F4A8}",
|
|
568
|
-
"\u{1FA84}",
|
|
569
|
-
"\u{1F972}",
|
|
570
|
-
"\u{1F485}",
|
|
571
|
-
"\u{1FAE6}",
|
|
572
|
-
"\u{1F92F}",
|
|
573
|
-
"\u{1F31A}",
|
|
574
|
-
"\u{1F441}\uFE0F",
|
|
575
|
-
"\u{1FAC0}",
|
|
576
|
-
"\u{1F98B}",
|
|
577
|
-
"\u{1FA90}"
|
|
578
|
-
];
|
|
579
|
-
var EmojiPicker = ({ onPick, onClose, isOwn }) => {
|
|
580
|
-
const ref = useRef4(null);
|
|
658
|
+
// src/react/components/Chat/Chat.tsx
|
|
659
|
+
import { useState as useState7, useEffect as useEffect6, useCallback as useCallback8, useMemo } from "react";
|
|
660
|
+
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
661
|
+
var Chat = ({
|
|
662
|
+
client,
|
|
663
|
+
theme = "light",
|
|
664
|
+
customClasses,
|
|
665
|
+
initialNavOpen = false,
|
|
666
|
+
children
|
|
667
|
+
}) => {
|
|
668
|
+
const [activeRoom, setActiveRoom] = useState7(void 0);
|
|
669
|
+
const [navOpen, setNavOpen] = useState7(initialNavOpen);
|
|
670
|
+
const [currentUser, setCurrentUser] = useState7(
|
|
671
|
+
client.currentUser
|
|
672
|
+
);
|
|
581
673
|
useEffect6(() => {
|
|
582
|
-
|
|
583
|
-
|
|
674
|
+
if (client.currentUser) {
|
|
675
|
+
setCurrentUser(client.currentUser);
|
|
676
|
+
}
|
|
677
|
+
const onConnected = () => setCurrentUser(client.currentUser);
|
|
678
|
+
client.on("connected", onConnected);
|
|
679
|
+
return () => {
|
|
680
|
+
client.off("connected", onConnected);
|
|
584
681
|
};
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
682
|
+
}, [client]);
|
|
683
|
+
const openMobileNav = useCallback8(() => setNavOpen(true), []);
|
|
684
|
+
const closeMobileNav = useCallback8(() => setNavOpen(false), []);
|
|
685
|
+
const handleSetActiveRoom = useCallback8(
|
|
686
|
+
(room) => {
|
|
687
|
+
setActiveRoom(room);
|
|
688
|
+
setNavOpen(false);
|
|
689
|
+
},
|
|
690
|
+
[]
|
|
691
|
+
);
|
|
692
|
+
const chatContextValue = useMemo(
|
|
693
|
+
() => ({
|
|
694
|
+
client,
|
|
695
|
+
currentUser,
|
|
696
|
+
theme,
|
|
697
|
+
activeRoom,
|
|
698
|
+
setActiveRoom: handleSetActiveRoom,
|
|
699
|
+
openMobileNav,
|
|
700
|
+
closeMobileNav,
|
|
701
|
+
navOpen,
|
|
702
|
+
customClasses
|
|
703
|
+
}),
|
|
704
|
+
[
|
|
705
|
+
client,
|
|
706
|
+
currentUser,
|
|
707
|
+
theme,
|
|
708
|
+
activeRoom,
|
|
709
|
+
handleSetActiveRoom,
|
|
710
|
+
openMobileNav,
|
|
711
|
+
closeMobileNav,
|
|
712
|
+
navOpen,
|
|
713
|
+
customClasses
|
|
714
|
+
]
|
|
715
|
+
);
|
|
716
|
+
const containerClass = customClasses?.chat || `hermes-chat hermes-chat--${theme}`;
|
|
717
|
+
return /* @__PURE__ */ jsx7(ChatProvider, { value: chatContextValue, children: /* @__PURE__ */ jsx7("div", { className: containerClass, children }) });
|
|
718
|
+
};
|
|
719
|
+
|
|
720
|
+
// src/react/components/Room/Room.tsx
|
|
721
|
+
import { useState as useState8, useCallback as useCallback9, useMemo as useMemo2, useEffect as useEffect7, useRef as useRef4 } from "react";
|
|
722
|
+
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
723
|
+
var Room = ({
|
|
724
|
+
roomId,
|
|
725
|
+
children,
|
|
726
|
+
// Component overrides forwarded to ComponentContext
|
|
727
|
+
Avatar: Avatar2,
|
|
728
|
+
Message: MessageOverride,
|
|
729
|
+
MessageStatus: MessageStatus2,
|
|
730
|
+
MessageActions: MessageActions2,
|
|
731
|
+
DateSeparator: DateSeparator2,
|
|
732
|
+
EmptyStateIndicator: EmptyStateIndicator2,
|
|
733
|
+
LoadingIndicator: LoadingIndicator2,
|
|
734
|
+
LoadingErrorIndicator: LoadingErrorIndicator2,
|
|
735
|
+
ReactionPicker: ReactionPicker2,
|
|
736
|
+
TypingIndicator: TypingIndicator2,
|
|
737
|
+
MediaMessage: MediaMessage2,
|
|
738
|
+
ThreadHeader: ThreadHeader2,
|
|
739
|
+
Modal: Modal2,
|
|
740
|
+
ChatInput: ChatInput2,
|
|
741
|
+
RoomListItem,
|
|
742
|
+
Search: Search2,
|
|
743
|
+
OnlineBadge: OnlineBadge2
|
|
744
|
+
}) => {
|
|
745
|
+
const { client, customClasses } = useChatContext("Room");
|
|
746
|
+
const [messages, setMessages] = useState8([]);
|
|
747
|
+
const [loading, setLoading] = useState8(true);
|
|
748
|
+
const [loadingMore, setLoadingMore] = useState8(false);
|
|
749
|
+
const [hasMore, setHasMore] = useState8(false);
|
|
750
|
+
const [error, setError] = useState8(null);
|
|
751
|
+
const oldestMessageId = useRef4(void 0);
|
|
752
|
+
const [thread, setThread] = useState8(null);
|
|
753
|
+
const [threadMessages, setThreadMessages] = useState8([]);
|
|
754
|
+
const [threadHasMore, setThreadHasMore] = useState8(false);
|
|
755
|
+
const [threadLoadingMore, setThreadLoadingMore] = useState8(false);
|
|
756
|
+
const [typingUsers, setTypingUsers] = useState8(
|
|
757
|
+
/* @__PURE__ */ new Map()
|
|
758
|
+
);
|
|
759
|
+
const typingTimeouts = useRef4(
|
|
760
|
+
/* @__PURE__ */ new Map()
|
|
761
|
+
);
|
|
762
|
+
const isTypingRef = useRef4(false);
|
|
763
|
+
const stopTypingTimeout = useRef4(null);
|
|
764
|
+
useEffect7(() => {
|
|
765
|
+
if (!roomId || !client?.isConnected) return;
|
|
766
|
+
setMessages([]);
|
|
767
|
+
setHasMore(false);
|
|
768
|
+
setThread(null);
|
|
769
|
+
setThreadMessages([]);
|
|
770
|
+
oldestMessageId.current = void 0;
|
|
771
|
+
setLoading(true);
|
|
772
|
+
setError(null);
|
|
773
|
+
client.getHistory(roomId).then(({ messages: msgs, hasMore: more }) => {
|
|
774
|
+
setMessages(msgs);
|
|
775
|
+
setHasMore(more);
|
|
776
|
+
if (msgs.length > 0) oldestMessageId.current = msgs[0]._id;
|
|
777
|
+
}).catch((err) => setError(err.message)).finally(() => setLoading(false));
|
|
778
|
+
}, [roomId, client?.isConnected]);
|
|
779
|
+
useEffect7(() => {
|
|
780
|
+
if (!roomId || !client) return;
|
|
781
|
+
const onReceive = (msg) => {
|
|
782
|
+
if (msg.roomId !== roomId) return;
|
|
783
|
+
if (msg.threadParentId && thread && msg.threadParentId === thread._id) {
|
|
784
|
+
setThreadMessages(
|
|
785
|
+
(prev) => prev.find((m) => m._id === msg._id) ? prev : [...prev, msg]
|
|
786
|
+
);
|
|
787
|
+
setMessages(
|
|
788
|
+
(prev) => prev.map(
|
|
789
|
+
(m) => m._id === msg.threadParentId ? { ...m, replyCount: (m.replyCount || 0) + 1 } : m
|
|
790
|
+
)
|
|
791
|
+
);
|
|
792
|
+
return;
|
|
793
|
+
}
|
|
794
|
+
setMessages(
|
|
795
|
+
(prev) => prev.find((m) => m._id === msg._id) ? prev : [...prev, msg]
|
|
796
|
+
);
|
|
797
|
+
};
|
|
798
|
+
const onDeleted = ({ messageId }) => {
|
|
799
|
+
setMessages(
|
|
800
|
+
(prev) => prev.map(
|
|
801
|
+
(m) => m._id === messageId ? { ...m, isDeleted: true, text: void 0 } : m
|
|
802
|
+
)
|
|
803
|
+
);
|
|
804
|
+
setThreadMessages(
|
|
805
|
+
(prev) => prev.map(
|
|
806
|
+
(m) => m._id === messageId ? { ...m, isDeleted: true, text: void 0 } : m
|
|
807
|
+
)
|
|
808
|
+
);
|
|
809
|
+
};
|
|
810
|
+
const onEdited = (msg) => {
|
|
811
|
+
setMessages((prev) => prev.map((m) => m._id === msg._id ? msg : m));
|
|
812
|
+
setThreadMessages(
|
|
813
|
+
(prev) => prev.map((m) => m._id === msg._id ? msg : m)
|
|
814
|
+
);
|
|
815
|
+
};
|
|
816
|
+
const onReaction = ({ messageId, reactions }) => {
|
|
817
|
+
setMessages(
|
|
818
|
+
(prev) => prev.map((m) => m._id === messageId ? { ...m, reactions } : m)
|
|
819
|
+
);
|
|
820
|
+
setThreadMessages(
|
|
821
|
+
(prev) => prev.map((m) => m._id === messageId ? { ...m, reactions } : m)
|
|
822
|
+
);
|
|
823
|
+
};
|
|
824
|
+
client.on("message:receive", onReceive);
|
|
825
|
+
client.on("message:deleted", onDeleted);
|
|
826
|
+
client.on("message:edited", onEdited);
|
|
827
|
+
client.on("reaction:updated", onReaction);
|
|
828
|
+
return () => {
|
|
829
|
+
client.off("message:receive", onReceive);
|
|
830
|
+
client.off("message:deleted", onDeleted);
|
|
831
|
+
client.off("message:edited", onEdited);
|
|
832
|
+
client.off("reaction:updated", onReaction);
|
|
833
|
+
};
|
|
834
|
+
}, [roomId, client, thread]);
|
|
835
|
+
useEffect7(() => {
|
|
836
|
+
if (!roomId || !client) return;
|
|
837
|
+
const onStart = (event) => {
|
|
838
|
+
if (event.roomId !== roomId) return;
|
|
839
|
+
if (event.userId === client.currentUser?.userId) return;
|
|
840
|
+
setTypingUsers(
|
|
841
|
+
(prev) => new Map(prev).set(event.userId, event.displayName)
|
|
842
|
+
);
|
|
843
|
+
const existing = typingTimeouts.current.get(event.userId);
|
|
844
|
+
if (existing) clearTimeout(existing);
|
|
845
|
+
const t = setTimeout(() => {
|
|
846
|
+
setTypingUsers((prev) => {
|
|
847
|
+
const next = new Map(prev);
|
|
848
|
+
next.delete(event.userId);
|
|
849
|
+
return next;
|
|
850
|
+
});
|
|
851
|
+
}, 4e3);
|
|
852
|
+
typingTimeouts.current.set(event.userId, t);
|
|
853
|
+
};
|
|
854
|
+
const onStop = (event) => {
|
|
855
|
+
if (event.roomId !== roomId) return;
|
|
856
|
+
setTypingUsers((prev) => {
|
|
857
|
+
const next = new Map(prev);
|
|
858
|
+
next.delete(event.userId);
|
|
859
|
+
return next;
|
|
860
|
+
});
|
|
861
|
+
const existing = typingTimeouts.current.get(event.userId);
|
|
862
|
+
if (existing) clearTimeout(existing);
|
|
863
|
+
};
|
|
864
|
+
client.on("typing:started", onStart);
|
|
865
|
+
client.on("typing:stopped", onStop);
|
|
866
|
+
return () => {
|
|
867
|
+
client.off("typing:started", onStart);
|
|
868
|
+
client.off("typing:stopped", onStop);
|
|
869
|
+
typingTimeouts.current.forEach(clearTimeout);
|
|
870
|
+
typingTimeouts.current.clear();
|
|
871
|
+
setTypingUsers(/* @__PURE__ */ new Map());
|
|
872
|
+
};
|
|
873
|
+
}, [roomId, client]);
|
|
874
|
+
const sendMessage = useCallback9(
|
|
875
|
+
async (input) => {
|
|
876
|
+
if (!roomId) throw new Error("No room selected");
|
|
877
|
+
return client.sendMessage({ ...input, roomId });
|
|
878
|
+
},
|
|
879
|
+
[roomId, client]
|
|
880
|
+
);
|
|
881
|
+
const editMessage = useCallback9(
|
|
882
|
+
async (messageId, text) => {
|
|
883
|
+
if (!roomId) throw new Error("No room selected");
|
|
884
|
+
return client.editMessage(messageId, roomId, text);
|
|
885
|
+
},
|
|
886
|
+
[roomId, client]
|
|
887
|
+
);
|
|
888
|
+
const deleteMessage = useCallback9(
|
|
889
|
+
async (messageId) => {
|
|
890
|
+
if (!roomId) throw new Error("No room selected");
|
|
891
|
+
return client.deleteMessage(messageId, roomId);
|
|
892
|
+
},
|
|
893
|
+
[roomId, client]
|
|
894
|
+
);
|
|
895
|
+
const addReaction = useCallback9(
|
|
896
|
+
async (messageId, emoji) => {
|
|
897
|
+
if (!roomId) throw new Error("No room selected");
|
|
898
|
+
return client.addReaction(messageId, roomId, emoji);
|
|
899
|
+
},
|
|
900
|
+
[roomId, client]
|
|
901
|
+
);
|
|
902
|
+
const loadMore = useCallback9(async () => {
|
|
903
|
+
if (!roomId || loadingMore || !hasMore) return;
|
|
904
|
+
setLoadingMore(true);
|
|
905
|
+
try {
|
|
906
|
+
const { messages: older, hasMore: more } = await client.getHistory(
|
|
907
|
+
roomId,
|
|
908
|
+
oldestMessageId.current
|
|
909
|
+
);
|
|
910
|
+
setMessages((prev) => [...older, ...prev]);
|
|
911
|
+
setHasMore(more);
|
|
912
|
+
if (older.length > 0) oldestMessageId.current = older[0]._id;
|
|
913
|
+
} catch (err) {
|
|
914
|
+
setError(err.message);
|
|
915
|
+
} finally {
|
|
916
|
+
setLoadingMore(false);
|
|
917
|
+
}
|
|
918
|
+
}, [roomId, loadingMore, hasMore, client]);
|
|
919
|
+
const markRead = useCallback9(
|
|
920
|
+
async (lastMessageId) => {
|
|
921
|
+
if (!roomId) return;
|
|
922
|
+
await client.markSeen(roomId, lastMessageId);
|
|
923
|
+
},
|
|
924
|
+
[roomId, client]
|
|
925
|
+
);
|
|
926
|
+
const openThread = useCallback9((message) => {
|
|
927
|
+
setThread(message);
|
|
928
|
+
setThreadMessages([]);
|
|
929
|
+
setThreadHasMore(false);
|
|
930
|
+
}, []);
|
|
931
|
+
const closeThread = useCallback9(() => {
|
|
932
|
+
setThread(null);
|
|
933
|
+
setThreadMessages([]);
|
|
934
|
+
}, []);
|
|
935
|
+
const loadMoreThread = useCallback9(async () => {
|
|
936
|
+
}, []);
|
|
937
|
+
const startTyping = useCallback9(() => {
|
|
938
|
+
if (!roomId) return;
|
|
939
|
+
if (!isTypingRef.current) {
|
|
940
|
+
client.startTyping(roomId);
|
|
941
|
+
isTypingRef.current = true;
|
|
942
|
+
}
|
|
943
|
+
if (stopTypingTimeout.current) clearTimeout(stopTypingTimeout.current);
|
|
944
|
+
stopTypingTimeout.current = setTimeout(() => {
|
|
945
|
+
client.stopTyping(roomId);
|
|
946
|
+
isTypingRef.current = false;
|
|
947
|
+
}, 3e3);
|
|
948
|
+
}, [roomId, client]);
|
|
949
|
+
const stopTyping = useCallback9(() => {
|
|
950
|
+
if (!roomId) return;
|
|
951
|
+
if (stopTypingTimeout.current) clearTimeout(stopTypingTimeout.current);
|
|
952
|
+
if (isTypingRef.current) {
|
|
953
|
+
client.stopTyping(roomId);
|
|
954
|
+
isTypingRef.current = false;
|
|
955
|
+
}
|
|
956
|
+
}, [roomId, client]);
|
|
957
|
+
const typingText = useMemo2(() => {
|
|
958
|
+
const names = Array.from(typingUsers.values());
|
|
959
|
+
if (names.length === 0) return null;
|
|
960
|
+
if (names.length === 1) return `${names[0]} is typing...`;
|
|
961
|
+
if (names.length === 2) return `${names[0]} and ${names[1]} are typing...`;
|
|
962
|
+
return `${names[0]} and ${names.length - 1} others are typing...`;
|
|
963
|
+
}, [typingUsers]);
|
|
964
|
+
const roomStateValue = useMemo2(
|
|
965
|
+
() => ({
|
|
966
|
+
room: { _id: roomId },
|
|
967
|
+
messages,
|
|
968
|
+
loading,
|
|
969
|
+
loadingMore,
|
|
970
|
+
hasMore,
|
|
971
|
+
error,
|
|
972
|
+
members: [],
|
|
973
|
+
thread,
|
|
974
|
+
threadMessages,
|
|
975
|
+
threadHasMore,
|
|
976
|
+
threadLoadingMore,
|
|
977
|
+
pinnedMessages: messages.filter((m) => m.pinnedAt)
|
|
978
|
+
}),
|
|
979
|
+
[messages, loading, loadingMore, hasMore, error, thread, threadMessages, threadHasMore, threadLoadingMore, roomId]
|
|
980
|
+
);
|
|
981
|
+
const roomActionValue = useMemo2(
|
|
982
|
+
() => ({
|
|
983
|
+
sendMessage,
|
|
984
|
+
editMessage,
|
|
985
|
+
deleteMessage,
|
|
986
|
+
addReaction,
|
|
987
|
+
loadMore,
|
|
988
|
+
markRead,
|
|
989
|
+
openThread,
|
|
990
|
+
closeThread,
|
|
991
|
+
loadMoreThread
|
|
992
|
+
}),
|
|
993
|
+
[sendMessage, editMessage, deleteMessage, addReaction, loadMore, markRead, openThread, closeThread, loadMoreThread]
|
|
994
|
+
);
|
|
995
|
+
const typingValue = useMemo2(
|
|
996
|
+
() => ({
|
|
997
|
+
typingUsers,
|
|
998
|
+
typingText,
|
|
999
|
+
isAnyoneTyping: typingUsers.size > 0,
|
|
1000
|
+
startTyping,
|
|
1001
|
+
stopTyping
|
|
1002
|
+
}),
|
|
1003
|
+
[typingUsers, typingText, startTyping, stopTyping]
|
|
1004
|
+
);
|
|
1005
|
+
const componentOverrides = useMemo2(
|
|
1006
|
+
() => ({
|
|
1007
|
+
Avatar: Avatar2,
|
|
1008
|
+
Message: MessageOverride,
|
|
1009
|
+
MessageStatus: MessageStatus2,
|
|
1010
|
+
MessageActions: MessageActions2,
|
|
1011
|
+
DateSeparator: DateSeparator2,
|
|
1012
|
+
EmptyStateIndicator: EmptyStateIndicator2,
|
|
1013
|
+
LoadingIndicator: LoadingIndicator2,
|
|
1014
|
+
LoadingErrorIndicator: LoadingErrorIndicator2,
|
|
1015
|
+
ReactionPicker: ReactionPicker2,
|
|
1016
|
+
TypingIndicator: TypingIndicator2,
|
|
1017
|
+
MediaMessage: MediaMessage2,
|
|
1018
|
+
ThreadHeader: ThreadHeader2,
|
|
1019
|
+
Modal: Modal2,
|
|
1020
|
+
ChatInput: ChatInput2,
|
|
1021
|
+
RoomListItem,
|
|
1022
|
+
Search: Search2,
|
|
1023
|
+
OnlineBadge: OnlineBadge2
|
|
1024
|
+
}),
|
|
1025
|
+
[Avatar2, MessageOverride, MessageStatus2, MessageActions2, DateSeparator2, EmptyStateIndicator2, LoadingIndicator2, LoadingErrorIndicator2, ReactionPicker2, TypingIndicator2, MediaMessage2, ThreadHeader2, Modal2, ChatInput2, RoomListItem, Search2, OnlineBadge2]
|
|
1026
|
+
);
|
|
1027
|
+
const containerClass = customClasses?.room || "hermes-room";
|
|
1028
|
+
return /* @__PURE__ */ jsx8(RoomStateProvider, { value: roomStateValue, children: /* @__PURE__ */ jsx8(RoomActionProvider, { value: roomActionValue, children: /* @__PURE__ */ jsx8(TypingProvider, { value: typingValue, children: /* @__PURE__ */ jsx8(ComponentProvider, { value: componentOverrides, children: /* @__PURE__ */ jsx8("div", { className: containerClass, children }) }) }) }) });
|
|
1029
|
+
};
|
|
1030
|
+
|
|
1031
|
+
// src/react/components/Window/Window.tsx
|
|
1032
|
+
import { jsx as jsx9 } from "react/jsx-runtime";
|
|
1033
|
+
var Window = ({
|
|
1034
|
+
className = "",
|
|
1035
|
+
children
|
|
1036
|
+
}) => {
|
|
1037
|
+
const { customClasses } = useChatContext("Window");
|
|
1038
|
+
const containerClass = customClasses?.window || `hermes-window ${className}`.trim();
|
|
1039
|
+
return /* @__PURE__ */ jsx9(
|
|
589
1040
|
"div",
|
|
590
1041
|
{
|
|
591
|
-
|
|
1042
|
+
className: containerClass,
|
|
592
1043
|
style: {
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
borderRadius: 14,
|
|
600
|
-
padding: "8px 10px",
|
|
601
|
-
boxShadow: "0 8px 32px rgba(0,0,0,0.4)",
|
|
602
|
-
display: "grid",
|
|
603
|
-
gridTemplateColumns: "repeat(5, 1fr)",
|
|
604
|
-
gap: 4,
|
|
605
|
-
animation: "hermes-pop 0.15s ease"
|
|
1044
|
+
display: "flex",
|
|
1045
|
+
flexDirection: "column",
|
|
1046
|
+
height: "100%",
|
|
1047
|
+
flex: 1,
|
|
1048
|
+
minWidth: 0,
|
|
1049
|
+
overflow: "hidden"
|
|
606
1050
|
},
|
|
607
|
-
children
|
|
608
|
-
"button",
|
|
609
|
-
{
|
|
610
|
-
onClick: () => {
|
|
611
|
-
onPick(emoji);
|
|
612
|
-
onClose();
|
|
613
|
-
},
|
|
614
|
-
style: {
|
|
615
|
-
background: "none",
|
|
616
|
-
border: "none",
|
|
617
|
-
cursor: "pointer",
|
|
618
|
-
fontSize: 20,
|
|
619
|
-
padding: "4px",
|
|
620
|
-
borderRadius: 8,
|
|
621
|
-
lineHeight: 1,
|
|
622
|
-
transition: "transform 0.1s, background 0.1s"
|
|
623
|
-
},
|
|
624
|
-
onMouseEnter: (e) => {
|
|
625
|
-
e.currentTarget.style.transform = "scale(1.3)";
|
|
626
|
-
e.currentTarget.style.background = "rgba(255,255,255,0.08)";
|
|
627
|
-
},
|
|
628
|
-
onMouseLeave: (e) => {
|
|
629
|
-
e.currentTarget.style.transform = "scale(1)";
|
|
630
|
-
e.currentTarget.style.background = "none";
|
|
631
|
-
},
|
|
632
|
-
children: emoji
|
|
633
|
-
},
|
|
634
|
-
emoji
|
|
635
|
-
))
|
|
1051
|
+
children
|
|
636
1052
|
}
|
|
637
1053
|
);
|
|
638
1054
|
};
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
1055
|
+
|
|
1056
|
+
// src/react/components/MessageList.tsx
|
|
1057
|
+
import React10, { useEffect as useEffect9, useRef as useRef6 } from "react";
|
|
1058
|
+
|
|
1059
|
+
// src/react/components/Message/Message.tsx
|
|
1060
|
+
import { useState as useState9, useRef as useRef5, useEffect as useEffect8 } from "react";
|
|
1061
|
+
|
|
1062
|
+
// src/react/components/Avatar/Avatar.tsx
|
|
1063
|
+
import { jsx as jsx10, jsxs } from "react/jsx-runtime";
|
|
1064
|
+
var getInitials = (name) => {
|
|
1065
|
+
if (!name) return "?";
|
|
1066
|
+
const parts = name.trim().split(/\s+/);
|
|
1067
|
+
if (parts.length >= 2) return `${parts[0][0]}${parts[1][0]}`.toUpperCase();
|
|
1068
|
+
return name.slice(0, 2).toUpperCase();
|
|
1069
|
+
};
|
|
1070
|
+
var Avatar = ({
|
|
1071
|
+
image,
|
|
1072
|
+
name,
|
|
1073
|
+
size = 36,
|
|
1074
|
+
shape = "circle",
|
|
1075
|
+
className = "",
|
|
1076
|
+
online
|
|
1077
|
+
}) => {
|
|
1078
|
+
const borderRadius = shape === "circle" ? "50%" : shape === "rounded" ? "8px" : "0";
|
|
642
1079
|
return /* @__PURE__ */ jsxs(
|
|
643
1080
|
"div",
|
|
644
1081
|
{
|
|
1082
|
+
className: `hermes-avatar ${className}`,
|
|
645
1083
|
style: {
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
minHeight: 28
|
|
1084
|
+
position: "relative",
|
|
1085
|
+
width: size,
|
|
1086
|
+
height: size,
|
|
1087
|
+
flexShrink: 0
|
|
651
1088
|
},
|
|
652
1089
|
children: [
|
|
653
|
-
/* @__PURE__ */
|
|
1090
|
+
image ? /* @__PURE__ */ jsx10(
|
|
1091
|
+
"img",
|
|
1092
|
+
{
|
|
1093
|
+
src: image,
|
|
1094
|
+
alt: name || "avatar",
|
|
1095
|
+
style: {
|
|
1096
|
+
width: size,
|
|
1097
|
+
height: size,
|
|
1098
|
+
borderRadius,
|
|
1099
|
+
objectFit: "cover",
|
|
1100
|
+
display: "block"
|
|
1101
|
+
}
|
|
1102
|
+
}
|
|
1103
|
+
) : /* @__PURE__ */ jsx10(
|
|
654
1104
|
"div",
|
|
655
1105
|
{
|
|
656
1106
|
style: {
|
|
1107
|
+
width: size,
|
|
1108
|
+
height: size,
|
|
1109
|
+
borderRadius,
|
|
1110
|
+
background: "linear-gradient(135deg, #667eea 0%, #764ba2 100%)",
|
|
657
1111
|
display: "flex",
|
|
658
1112
|
alignItems: "center",
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
1113
|
+
justifyContent: "center",
|
|
1114
|
+
color: "#fff",
|
|
1115
|
+
fontWeight: 700,
|
|
1116
|
+
fontSize: size * 0.38,
|
|
1117
|
+
userSelect: "none"
|
|
663
1118
|
},
|
|
664
|
-
children:
|
|
665
|
-
"span",
|
|
666
|
-
{
|
|
667
|
-
style: {
|
|
668
|
-
width: 6,
|
|
669
|
-
height: 6,
|
|
670
|
-
borderRadius: "50%",
|
|
671
|
-
background: "#999",
|
|
672
|
-
display: "block",
|
|
673
|
-
animation: `hermes-bounce 1.2s ease-in-out ${i * 0.18}s infinite`
|
|
674
|
-
}
|
|
675
|
-
},
|
|
676
|
-
i
|
|
677
|
-
))
|
|
1119
|
+
children: getInitials(name)
|
|
678
1120
|
}
|
|
679
1121
|
),
|
|
680
|
-
/* @__PURE__ */
|
|
1122
|
+
online !== void 0 && /* @__PURE__ */ jsx10(
|
|
1123
|
+
"span",
|
|
1124
|
+
{
|
|
1125
|
+
style: {
|
|
1126
|
+
position: "absolute",
|
|
1127
|
+
bottom: 0,
|
|
1128
|
+
right: 0,
|
|
1129
|
+
width: size * 0.3,
|
|
1130
|
+
height: size * 0.3,
|
|
1131
|
+
borderRadius: "50%",
|
|
1132
|
+
background: online ? "#22c55e" : "#9ca3af",
|
|
1133
|
+
border: "2px solid #fff"
|
|
1134
|
+
}
|
|
1135
|
+
}
|
|
1136
|
+
)
|
|
681
1137
|
]
|
|
682
1138
|
}
|
|
683
1139
|
);
|
|
684
1140
|
};
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
1141
|
+
|
|
1142
|
+
// src/react/components/Message/MessageStatus.tsx
|
|
1143
|
+
import { jsx as jsx11 } from "react/jsx-runtime";
|
|
1144
|
+
var MessageStatus = ({
|
|
1145
|
+
status,
|
|
1146
|
+
seenCount = 0,
|
|
1147
|
+
isMyMessage = true,
|
|
1148
|
+
className = ""
|
|
1149
|
+
}) => {
|
|
1150
|
+
if (!isMyMessage) return null;
|
|
1151
|
+
const color = status === "seen" ? "#0084ff" : "rgba(128,128,128,0.6)";
|
|
1152
|
+
const checks = status === "sent" ? "\u2713" : "\u2713\u2713";
|
|
1153
|
+
return /* @__PURE__ */ jsx11(
|
|
1154
|
+
"span",
|
|
1155
|
+
{
|
|
1156
|
+
className: `hermes-message-status ${className}`,
|
|
1157
|
+
title: status === "seen" ? `Seen by ${seenCount} ${seenCount === 1 ? "person" : "people"}` : status === "delivered" ? "Delivered" : "Sent",
|
|
1158
|
+
style: {
|
|
1159
|
+
fontSize: 11,
|
|
1160
|
+
color,
|
|
1161
|
+
marginLeft: 4,
|
|
1162
|
+
userSelect: "none"
|
|
1163
|
+
},
|
|
1164
|
+
children: checks
|
|
1165
|
+
}
|
|
1166
|
+
);
|
|
1167
|
+
};
|
|
1168
|
+
|
|
1169
|
+
// src/react/components/Message/MessageActions.tsx
|
|
1170
|
+
import { jsx as jsx12, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
1171
|
+
var ActionBtn = ({ onClick, title, children }) => /* @__PURE__ */ jsx12(
|
|
1172
|
+
"button",
|
|
1173
|
+
{
|
|
1174
|
+
onClick,
|
|
1175
|
+
title,
|
|
1176
|
+
style: {
|
|
1177
|
+
background: "#fff",
|
|
1178
|
+
border: "1px solid rgba(0,0,0,0.1)",
|
|
1179
|
+
borderRadius: 8,
|
|
1180
|
+
cursor: "pointer",
|
|
1181
|
+
fontSize: 14,
|
|
1182
|
+
padding: "3px 6px",
|
|
1183
|
+
lineHeight: 1,
|
|
1184
|
+
boxShadow: "0 1px 4px rgba(0,0,0,0.1)",
|
|
1185
|
+
transition: "transform 0.1s"
|
|
1186
|
+
},
|
|
1187
|
+
onMouseEnter: (e) => e.currentTarget.style.transform = "scale(1.15)",
|
|
1188
|
+
onMouseLeave: (e) => e.currentTarget.style.transform = "scale(1)",
|
|
1189
|
+
children
|
|
1190
|
+
}
|
|
1191
|
+
);
|
|
1192
|
+
var MessageActions = ({
|
|
1193
|
+
isOwn,
|
|
1194
|
+
isText,
|
|
1195
|
+
hasThread = false,
|
|
1196
|
+
replyCount = 0,
|
|
1197
|
+
onReact,
|
|
1198
|
+
onReply,
|
|
1199
|
+
onThread,
|
|
1200
|
+
onEdit,
|
|
1201
|
+
onDelete,
|
|
1202
|
+
onPin,
|
|
1203
|
+
className = ""
|
|
1204
|
+
}) => /* @__PURE__ */ jsxs2(
|
|
1205
|
+
"div",
|
|
1206
|
+
{
|
|
1207
|
+
className: `hermes-message-actions ${className}`,
|
|
1208
|
+
style: {
|
|
1209
|
+
display: "flex",
|
|
1210
|
+
flexDirection: isOwn ? "row-reverse" : "row",
|
|
1211
|
+
gap: 2
|
|
1212
|
+
},
|
|
1213
|
+
children: [
|
|
1214
|
+
onReact && /* @__PURE__ */ jsx12(ActionBtn, { onClick: onReact, title: "React", children: "\u{1F60A}" }),
|
|
1215
|
+
onReply && /* @__PURE__ */ jsx12(ActionBtn, { onClick: onReply, title: "Reply", children: "\u21A9" }),
|
|
1216
|
+
onThread && /* @__PURE__ */ jsx12(ActionBtn, { onClick: onThread, title: `Thread${replyCount > 0 ? ` (${replyCount})` : ""}`, children: "\u{1F9F5}" }),
|
|
1217
|
+
isOwn && isText && onEdit && /* @__PURE__ */ jsx12(ActionBtn, { onClick: onEdit, title: "Edit", children: "\u270F\uFE0F" }),
|
|
1218
|
+
onPin && /* @__PURE__ */ jsx12(ActionBtn, { onClick: onPin, title: "Pin", children: "\u{1F4CC}" }),
|
|
1219
|
+
isOwn && onDelete && /* @__PURE__ */ jsx12(ActionBtn, { onClick: onDelete, title: "Delete", children: "\u{1F5D1}" })
|
|
1220
|
+
]
|
|
1221
|
+
}
|
|
1222
|
+
);
|
|
1223
|
+
|
|
1224
|
+
// src/react/components/Message/Message.tsx
|
|
1225
|
+
import { jsx as jsx13, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
1226
|
+
var REACTION_EMOJIS = ["\u{1F44D}", "\u2764\uFE0F", "\u{1F602}", "\u{1F62E}", "\u{1F622}", "\u{1F525}", "\u{1F389}", "\u{1F44F}"];
|
|
1227
|
+
var formatTime = (iso) => new Date(iso).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" });
|
|
1228
|
+
var formatFileSize = (bytes) => {
|
|
1229
|
+
if (!bytes) return "";
|
|
1230
|
+
if (bytes >= 1024 * 1024) return `${(bytes / 1024 / 1024).toFixed(1)} MB`;
|
|
1231
|
+
if (bytes >= 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
1232
|
+
return `${bytes} B`;
|
|
1233
|
+
};
|
|
1234
|
+
var Message = ({
|
|
1235
|
+
message,
|
|
1236
|
+
isOwn,
|
|
1237
|
+
onEdit,
|
|
1238
|
+
onDelete,
|
|
1239
|
+
onReact,
|
|
1240
|
+
onReply,
|
|
1241
|
+
onOpenThread,
|
|
1242
|
+
onPin,
|
|
1243
|
+
renderAvatar,
|
|
1244
|
+
senderName,
|
|
1245
|
+
senderImage,
|
|
1246
|
+
groupStyle = "single",
|
|
1247
|
+
className = "",
|
|
1248
|
+
showAvatar = true
|
|
1249
|
+
}) => {
|
|
1250
|
+
const [hovered, setHovered] = useState9(false);
|
|
1251
|
+
const [pickerOpen, setPickerOpen] = useState9(false);
|
|
1252
|
+
const pickerRef = useRef5(null);
|
|
1253
|
+
useEffect8(() => {
|
|
1254
|
+
if (!pickerOpen) return;
|
|
1255
|
+
const handler = (e) => {
|
|
1256
|
+
if (pickerRef.current && !pickerRef.current.contains(e.target)) {
|
|
1257
|
+
setPickerOpen(false);
|
|
1258
|
+
}
|
|
1259
|
+
};
|
|
1260
|
+
document.addEventListener("mousedown", handler);
|
|
1261
|
+
return () => document.removeEventListener("mousedown", handler);
|
|
1262
|
+
}, [pickerOpen]);
|
|
1263
|
+
if (message.isDeleted) {
|
|
1264
|
+
return /* @__PURE__ */ jsx13(
|
|
1265
|
+
"div",
|
|
1266
|
+
{
|
|
1267
|
+
className: `hermes-message hermes-message--deleted ${className}`,
|
|
1268
|
+
style: {
|
|
693
1269
|
opacity: 0.5,
|
|
694
1270
|
fontStyle: "italic",
|
|
695
1271
|
padding: "4px 16px",
|
|
@@ -699,40 +1275,24 @@ var DefaultMessage = ({ message, isOwn, onEdit, onDelete, onReact, onReply, rend
|
|
|
699
1275
|
}
|
|
700
1276
|
);
|
|
701
1277
|
}
|
|
702
|
-
|
|
1278
|
+
const showAvatarSlot = showAvatar && !isOwn && (groupStyle === "bottom" || groupStyle === "single");
|
|
1279
|
+
return /* @__PURE__ */ jsxs3(
|
|
703
1280
|
"div",
|
|
704
1281
|
{
|
|
1282
|
+
className: `hermes-message ${isOwn ? "hermes-message--own" : "hermes-message--other"} ${className}`,
|
|
705
1283
|
onMouseEnter: () => setHovered(true),
|
|
706
|
-
onMouseLeave: () =>
|
|
707
|
-
setHovered(false);
|
|
708
|
-
},
|
|
1284
|
+
onMouseLeave: () => setHovered(false),
|
|
709
1285
|
style: {
|
|
710
1286
|
display: "flex",
|
|
711
1287
|
flexDirection: isOwn ? "row-reverse" : "row",
|
|
712
1288
|
alignItems: "flex-end",
|
|
713
1289
|
gap: 8,
|
|
714
|
-
marginBottom:
|
|
1290
|
+
marginBottom: groupStyle === "bottom" || groupStyle === "single" ? 8 : 2,
|
|
715
1291
|
position: "relative"
|
|
716
1292
|
},
|
|
717
1293
|
children: [
|
|
718
|
-
!isOwn && /* @__PURE__ */
|
|
719
|
-
|
|
720
|
-
{
|
|
721
|
-
style: {
|
|
722
|
-
width: 32,
|
|
723
|
-
height: 32,
|
|
724
|
-
borderRadius: "50%",
|
|
725
|
-
background: "#e0e0e0",
|
|
726
|
-
display: "flex",
|
|
727
|
-
alignItems: "center",
|
|
728
|
-
justifyContent: "center",
|
|
729
|
-
fontSize: 12,
|
|
730
|
-
fontWeight: 600
|
|
731
|
-
},
|
|
732
|
-
children: message.senderId.slice(-2).toUpperCase()
|
|
733
|
-
}
|
|
734
|
-
) }),
|
|
735
|
-
/* @__PURE__ */ jsxs(
|
|
1294
|
+
!isOwn && /* @__PURE__ */ jsx13("div", { style: { flexShrink: 0, width: 32 }, children: showAvatarSlot ? renderAvatar ? renderAvatar(message.senderId) : /* @__PURE__ */ jsx13(Avatar, { image: senderImage, name: senderName || message.senderId, size: 32 }) : null }),
|
|
1295
|
+
/* @__PURE__ */ jsxs3(
|
|
736
1296
|
"div",
|
|
737
1297
|
{
|
|
738
1298
|
style: {
|
|
@@ -742,13 +1302,10 @@ var DefaultMessage = ({ message, isOwn, onEdit, onDelete, onReact, onReply, rend
|
|
|
742
1302
|
alignItems: isOwn ? "flex-end" : "flex-start"
|
|
743
1303
|
},
|
|
744
1304
|
children: [
|
|
745
|
-
(onEdit || onDelete || onReact || onReply) && /* @__PURE__ */
|
|
1305
|
+
(onEdit || onDelete || onReact || onReply || onOpenThread) && /* @__PURE__ */ jsxs3(
|
|
746
1306
|
"div",
|
|
747
1307
|
{
|
|
748
1308
|
style: {
|
|
749
|
-
display: "flex",
|
|
750
|
-
flexDirection: isOwn ? "row-reverse" : "row",
|
|
751
|
-
gap: 2,
|
|
752
1309
|
marginBottom: 4,
|
|
753
1310
|
opacity: hovered ? 1 : 0,
|
|
754
1311
|
pointerEvents: hovered ? "auto" : "none",
|
|
@@ -756,55 +1313,86 @@ var DefaultMessage = ({ message, isOwn, onEdit, onDelete, onReact, onReply, rend
|
|
|
756
1313
|
position: "relative"
|
|
757
1314
|
},
|
|
758
1315
|
children: [
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
ActionBtn,
|
|
762
|
-
{
|
|
763
|
-
onClick: () => setPickerOpen((p) => !p),
|
|
764
|
-
title: "React",
|
|
765
|
-
children: "\u{1FAE0}"
|
|
766
|
-
}
|
|
767
|
-
),
|
|
768
|
-
pickerOpen && /* @__PURE__ */ jsx(
|
|
769
|
-
EmojiPicker,
|
|
770
|
-
{
|
|
771
|
-
isOwn,
|
|
772
|
-
onPick: (emoji) => onReact(message._id, emoji),
|
|
773
|
-
onClose: () => setPickerOpen(false)
|
|
774
|
-
}
|
|
775
|
-
)
|
|
776
|
-
] }),
|
|
777
|
-
onReply && /* @__PURE__ */ jsx(ActionBtn, { onClick: () => onReply(message), title: "Reply", children: "\u21A9" }),
|
|
778
|
-
isOwn && onEdit && message.type === "text" && /* @__PURE__ */ jsx(
|
|
779
|
-
ActionBtn,
|
|
1316
|
+
/* @__PURE__ */ jsx13(
|
|
1317
|
+
MessageActions,
|
|
780
1318
|
{
|
|
781
|
-
|
|
1319
|
+
isOwn,
|
|
1320
|
+
isText: message.type === "text",
|
|
1321
|
+
hasThread: !!message.replyCount && message.replyCount > 0,
|
|
1322
|
+
replyCount: message.replyCount,
|
|
1323
|
+
onReact: onReact ? () => setPickerOpen((p) => !p) : void 0,
|
|
1324
|
+
onReply: onReply ? () => onReply(message) : void 0,
|
|
1325
|
+
onThread: onOpenThread ? () => onOpenThread(message) : void 0,
|
|
1326
|
+
onEdit: onEdit ? () => {
|
|
782
1327
|
const text = window.prompt("Edit message:", message.text);
|
|
783
1328
|
if (text) onEdit(message._id, text);
|
|
784
|
-
},
|
|
785
|
-
|
|
786
|
-
|
|
1329
|
+
} : void 0,
|
|
1330
|
+
onDelete: onDelete ? () => onDelete(message._id) : void 0,
|
|
1331
|
+
onPin: onPin ? () => onPin(message) : void 0
|
|
787
1332
|
}
|
|
788
1333
|
),
|
|
789
|
-
|
|
1334
|
+
pickerOpen && onReact && /* @__PURE__ */ jsx13(
|
|
1335
|
+
"div",
|
|
1336
|
+
{
|
|
1337
|
+
ref: pickerRef,
|
|
1338
|
+
style: {
|
|
1339
|
+
position: "absolute",
|
|
1340
|
+
bottom: "calc(100% + 4px)",
|
|
1341
|
+
[isOwn ? "right" : "left"]: 0,
|
|
1342
|
+
zIndex: 100,
|
|
1343
|
+
background: "#1a1a2e",
|
|
1344
|
+
border: "1px solid rgba(255,255,255,0.1)",
|
|
1345
|
+
borderRadius: 14,
|
|
1346
|
+
padding: "8px 10px",
|
|
1347
|
+
boxShadow: "0 8px 32px rgba(0,0,0,0.4)",
|
|
1348
|
+
display: "flex",
|
|
1349
|
+
gap: 4,
|
|
1350
|
+
animation: "hermes-pop 0.15s ease"
|
|
1351
|
+
},
|
|
1352
|
+
children: REACTION_EMOJIS.map((emoji) => /* @__PURE__ */ jsx13(
|
|
1353
|
+
"button",
|
|
1354
|
+
{
|
|
1355
|
+
onClick: () => {
|
|
1356
|
+
onReact(message._id, emoji);
|
|
1357
|
+
setPickerOpen(false);
|
|
1358
|
+
},
|
|
1359
|
+
style: {
|
|
1360
|
+
background: "none",
|
|
1361
|
+
border: "none",
|
|
1362
|
+
cursor: "pointer",
|
|
1363
|
+
fontSize: 20,
|
|
1364
|
+
padding: "4px",
|
|
1365
|
+
borderRadius: 8,
|
|
1366
|
+
lineHeight: 1,
|
|
1367
|
+
transition: "transform 0.1s"
|
|
1368
|
+
},
|
|
1369
|
+
onMouseEnter: (e) => e.currentTarget.style.transform = "scale(1.3)",
|
|
1370
|
+
onMouseLeave: (e) => e.currentTarget.style.transform = "scale(1)",
|
|
1371
|
+
children: emoji
|
|
1372
|
+
},
|
|
1373
|
+
emoji
|
|
1374
|
+
))
|
|
1375
|
+
}
|
|
1376
|
+
)
|
|
790
1377
|
]
|
|
791
1378
|
}
|
|
792
1379
|
),
|
|
793
|
-
/* @__PURE__ */
|
|
1380
|
+
!isOwn && (groupStyle === "top" || groupStyle === "single") && senderName && /* @__PURE__ */ jsx13("span", { style: { fontSize: 11, fontWeight: 600, opacity: 0.6, marginBottom: 2, marginLeft: 4 }, children: senderName }),
|
|
1381
|
+
/* @__PURE__ */ jsxs3(
|
|
794
1382
|
"div",
|
|
795
1383
|
{
|
|
796
1384
|
style: {
|
|
797
1385
|
padding: "8px 12px",
|
|
798
|
-
borderRadius: isOwn ? "16px 16px 4px 16px" : "16px 16px 16px 4px",
|
|
1386
|
+
borderRadius: isOwn ? groupStyle === "top" || groupStyle === "single" ? "16px 16px 4px 16px" : "16px 4px 4px 16px" : groupStyle === "top" || groupStyle === "single" ? "16px 16px 16px 4px" : "4px 16px 16px 4px",
|
|
799
1387
|
background: isOwn ? "#0084ff" : "#f0f0f0",
|
|
800
1388
|
color: isOwn ? "#fff" : "#000"
|
|
801
1389
|
},
|
|
802
1390
|
children: [
|
|
803
|
-
message.replyTo && /* @__PURE__ */
|
|
1391
|
+
message.replyTo && /* @__PURE__ */ jsx13(
|
|
804
1392
|
"div",
|
|
805
1393
|
{
|
|
806
1394
|
style: {
|
|
807
|
-
borderLeft:
|
|
1395
|
+
borderLeft: `3px solid ${isOwn ? "rgba(255,255,255,0.4)" : "rgba(0,132,255,0.4)"}`,
|
|
808
1396
|
paddingLeft: 8,
|
|
809
1397
|
marginBottom: 6,
|
|
810
1398
|
fontSize: 12,
|
|
@@ -813,27 +1401,24 @@ var DefaultMessage = ({ message, isOwn, onEdit, onDelete, onReact, onReply, rend
|
|
|
813
1401
|
children: "Replying to a message"
|
|
814
1402
|
}
|
|
815
1403
|
),
|
|
816
|
-
message.type === "text" && /* @__PURE__ */
|
|
1404
|
+
message.type === "text" && /* @__PURE__ */ jsxs3("p", { style: { margin: 0, wordBreak: "break-word" }, children: [
|
|
817
1405
|
message.text,
|
|
818
|
-
message.editedAt && /* @__PURE__ */
|
|
1406
|
+
message.editedAt && /* @__PURE__ */ jsx13("span", { style: { fontSize: 10, opacity: 0.6, marginLeft: 6 }, children: "(edited)" })
|
|
819
1407
|
] }),
|
|
820
|
-
message.type === "link" && /* @__PURE__ */
|
|
821
|
-
message.text && /* @__PURE__ */
|
|
822
|
-
/* @__PURE__ */
|
|
1408
|
+
message.type === "link" && /* @__PURE__ */ jsxs3("div", { children: [
|
|
1409
|
+
message.text && /* @__PURE__ */ jsx13("p", { style: { margin: "0 0 4px" }, children: message.text }),
|
|
1410
|
+
/* @__PURE__ */ jsx13(
|
|
823
1411
|
"a",
|
|
824
1412
|
{
|
|
825
1413
|
href: message.url,
|
|
826
1414
|
target: "_blank",
|
|
827
1415
|
rel: "noopener noreferrer",
|
|
828
|
-
style: {
|
|
829
|
-
color: isOwn ? "#cce4ff" : "#0084ff",
|
|
830
|
-
wordBreak: "break-all"
|
|
831
|
-
},
|
|
1416
|
+
style: { color: isOwn ? "#cce4ff" : "#0084ff", wordBreak: "break-all" },
|
|
832
1417
|
children: message.url
|
|
833
1418
|
}
|
|
834
1419
|
)
|
|
835
1420
|
] }),
|
|
836
|
-
message.type === "image" && /* @__PURE__ */
|
|
1421
|
+
message.type === "image" && /* @__PURE__ */ jsx13(
|
|
837
1422
|
"img",
|
|
838
1423
|
{
|
|
839
1424
|
src: message.url,
|
|
@@ -841,16 +1426,17 @@ var DefaultMessage = ({ message, isOwn, onEdit, onDelete, onReact, onReply, rend
|
|
|
841
1426
|
style: { maxWidth: "100%", borderRadius: 8, display: "block" }
|
|
842
1427
|
}
|
|
843
1428
|
),
|
|
844
|
-
message.type === "video" && /* @__PURE__ */
|
|
1429
|
+
message.type === "video" && /* @__PURE__ */ jsx13(
|
|
845
1430
|
"video",
|
|
846
1431
|
{
|
|
847
1432
|
src: message.url,
|
|
1433
|
+
poster: message.thumbnail,
|
|
848
1434
|
controls: true,
|
|
849
1435
|
style: { maxWidth: "100%", borderRadius: 8 }
|
|
850
1436
|
}
|
|
851
1437
|
),
|
|
852
|
-
message.type === "audio" && /* @__PURE__ */
|
|
853
|
-
message.type === "document" && /* @__PURE__ */
|
|
1438
|
+
message.type === "audio" && /* @__PURE__ */ jsx13("audio", { src: message.url, controls: true, style: { width: "100%" } }),
|
|
1439
|
+
message.type === "document" && /* @__PURE__ */ jsxs3(
|
|
854
1440
|
"a",
|
|
855
1441
|
{
|
|
856
1442
|
href: message.url,
|
|
@@ -864,67 +1450,90 @@ var DefaultMessage = ({ message, isOwn, onEdit, onDelete, onReact, onReply, rend
|
|
|
864
1450
|
textDecoration: "none"
|
|
865
1451
|
},
|
|
866
1452
|
children: [
|
|
867
|
-
/* @__PURE__ */
|
|
868
|
-
/* @__PURE__ */
|
|
869
|
-
/* @__PURE__ */
|
|
870
|
-
/* @__PURE__ */
|
|
1453
|
+
/* @__PURE__ */ jsx13("span", { style: { fontSize: 24 }, children: "\u{1F4C4}" }),
|
|
1454
|
+
/* @__PURE__ */ jsxs3("div", { children: [
|
|
1455
|
+
/* @__PURE__ */ jsx13("div", { style: { fontWeight: 600, fontSize: 13 }, children: message.fileName }),
|
|
1456
|
+
/* @__PURE__ */ jsx13("div", { style: { fontSize: 11, opacity: 0.7 }, children: formatFileSize(message.fileSize) })
|
|
871
1457
|
] })
|
|
872
1458
|
]
|
|
873
1459
|
}
|
|
874
1460
|
),
|
|
875
|
-
/* @__PURE__ */
|
|
1461
|
+
/* @__PURE__ */ jsxs3(
|
|
876
1462
|
"div",
|
|
877
1463
|
{
|
|
878
1464
|
style: {
|
|
1465
|
+
display: "flex",
|
|
1466
|
+
alignItems: "center",
|
|
1467
|
+
justifyContent: "flex-end",
|
|
1468
|
+
gap: 4,
|
|
879
1469
|
fontSize: 10,
|
|
880
1470
|
opacity: 0.6,
|
|
881
|
-
textAlign: "right",
|
|
882
1471
|
marginTop: 4
|
|
883
1472
|
},
|
|
884
|
-
children:
|
|
1473
|
+
children: [
|
|
1474
|
+
formatTime(message.createdAt),
|
|
1475
|
+
message.pinnedAt && /* @__PURE__ */ jsx13("span", { title: "Pinned", children: "\u{1F4CC}" }),
|
|
1476
|
+
isOwn && /* @__PURE__ */ jsx13(
|
|
1477
|
+
MessageStatus,
|
|
1478
|
+
{
|
|
1479
|
+
status: message.deliveryStatus,
|
|
1480
|
+
seenCount: message.seenBy?.length || 0,
|
|
1481
|
+
isMyMessage: isOwn
|
|
1482
|
+
}
|
|
1483
|
+
)
|
|
1484
|
+
]
|
|
885
1485
|
}
|
|
886
1486
|
)
|
|
887
1487
|
]
|
|
888
1488
|
}
|
|
889
1489
|
),
|
|
890
|
-
message.
|
|
891
|
-
"
|
|
1490
|
+
message.replyCount && message.replyCount > 0 && onOpenThread && /* @__PURE__ */ jsxs3(
|
|
1491
|
+
"button",
|
|
892
1492
|
{
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
"
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
userSelect: "none"
|
|
910
|
-
},
|
|
911
|
-
onMouseEnter: (e) => e.currentTarget.style.transform = "scale(1.1)",
|
|
912
|
-
onMouseLeave: (e) => e.currentTarget.style.transform = "scale(1)",
|
|
913
|
-
children: [
|
|
914
|
-
r.emoji,
|
|
915
|
-
/* @__PURE__ */ jsx(
|
|
916
|
-
"span",
|
|
917
|
-
{
|
|
918
|
-
style: { fontSize: 11, fontWeight: 600, color: "#555" },
|
|
919
|
-
children: r.users.length
|
|
920
|
-
}
|
|
921
|
-
)
|
|
922
|
-
]
|
|
923
|
-
},
|
|
924
|
-
r.emoji
|
|
925
|
-
))
|
|
1493
|
+
onClick: () => onOpenThread(message),
|
|
1494
|
+
style: {
|
|
1495
|
+
background: "none",
|
|
1496
|
+
border: "none",
|
|
1497
|
+
color: "#0084ff",
|
|
1498
|
+
cursor: "pointer",
|
|
1499
|
+
fontSize: 12,
|
|
1500
|
+
fontWeight: 600,
|
|
1501
|
+
padding: "2px 4px",
|
|
1502
|
+
marginTop: 2
|
|
1503
|
+
},
|
|
1504
|
+
children: [
|
|
1505
|
+
message.replyCount,
|
|
1506
|
+
" ",
|
|
1507
|
+
message.replyCount === 1 ? "reply" : "replies"
|
|
1508
|
+
]
|
|
926
1509
|
}
|
|
927
|
-
)
|
|
1510
|
+
),
|
|
1511
|
+
message.reactions?.filter((r) => r.users.length > 0).length > 0 && /* @__PURE__ */ jsx13("div", { style: { display: "flex", gap: 4, flexWrap: "wrap", marginTop: 4 }, children: message.reactions.filter((r) => r.users.length > 0).map((r) => /* @__PURE__ */ jsxs3(
|
|
1512
|
+
"span",
|
|
1513
|
+
{
|
|
1514
|
+
onClick: () => onReact?.(message._id, r.emoji),
|
|
1515
|
+
style: {
|
|
1516
|
+
background: "#f0f0f0",
|
|
1517
|
+
border: "1px solid rgba(0,0,0,0.08)",
|
|
1518
|
+
borderRadius: 20,
|
|
1519
|
+
padding: "2px 8px",
|
|
1520
|
+
fontSize: 13,
|
|
1521
|
+
cursor: onReact ? "pointer" : "default",
|
|
1522
|
+
display: "flex",
|
|
1523
|
+
alignItems: "center",
|
|
1524
|
+
gap: 4,
|
|
1525
|
+
transition: "transform 0.1s",
|
|
1526
|
+
userSelect: "none"
|
|
1527
|
+
},
|
|
1528
|
+
onMouseEnter: (e) => e.currentTarget.style.transform = "scale(1.1)",
|
|
1529
|
+
onMouseLeave: (e) => e.currentTarget.style.transform = "scale(1)",
|
|
1530
|
+
children: [
|
|
1531
|
+
r.emoji,
|
|
1532
|
+
/* @__PURE__ */ jsx13("span", { style: { fontSize: 11, fontWeight: 600, color: "#555" }, children: r.users.length })
|
|
1533
|
+
]
|
|
1534
|
+
},
|
|
1535
|
+
r.emoji
|
|
1536
|
+
)) })
|
|
928
1537
|
]
|
|
929
1538
|
}
|
|
930
1539
|
)
|
|
@@ -932,52 +1541,277 @@ var DefaultMessage = ({ message, isOwn, onEdit, onDelete, onReact, onReply, rend
|
|
|
932
1541
|
}
|
|
933
1542
|
);
|
|
934
1543
|
};
|
|
935
|
-
|
|
936
|
-
|
|
1544
|
+
|
|
1545
|
+
// src/react/components/DateSeparator/DateSeparator.tsx
|
|
1546
|
+
import { jsx as jsx14, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1547
|
+
var defaultFormat = (date) => {
|
|
1548
|
+
const now = /* @__PURE__ */ new Date();
|
|
1549
|
+
const isToday = date.getDate() === now.getDate() && date.getMonth() === now.getMonth() && date.getFullYear() === now.getFullYear();
|
|
1550
|
+
const yesterday = new Date(now);
|
|
1551
|
+
yesterday.setDate(yesterday.getDate() - 1);
|
|
1552
|
+
const isYesterday = date.getDate() === yesterday.getDate() && date.getMonth() === yesterday.getMonth() && date.getFullYear() === yesterday.getFullYear();
|
|
1553
|
+
if (isToday) return "Today";
|
|
1554
|
+
if (isYesterday) return "Yesterday";
|
|
1555
|
+
return date.toLocaleDateString(void 0, {
|
|
1556
|
+
weekday: "long",
|
|
1557
|
+
year: "numeric",
|
|
1558
|
+
month: "long",
|
|
1559
|
+
day: "numeric"
|
|
1560
|
+
});
|
|
1561
|
+
};
|
|
1562
|
+
var DateSeparator = ({
|
|
1563
|
+
date,
|
|
1564
|
+
formatDate = defaultFormat,
|
|
1565
|
+
className = ""
|
|
1566
|
+
}) => /* @__PURE__ */ jsxs4(
|
|
1567
|
+
"div",
|
|
937
1568
|
{
|
|
938
|
-
|
|
939
|
-
title,
|
|
1569
|
+
className: `hermes-date-separator ${className}`,
|
|
940
1570
|
style: {
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
fontSize: 14,
|
|
946
|
-
padding: "3px 6px",
|
|
947
|
-
lineHeight: 1,
|
|
948
|
-
boxShadow: "0 1px 4px rgba(0,0,0,0.1)",
|
|
949
|
-
transition: "transform 0.1s"
|
|
1571
|
+
display: "flex",
|
|
1572
|
+
alignItems: "center",
|
|
1573
|
+
gap: 12,
|
|
1574
|
+
padding: "16px 0"
|
|
950
1575
|
},
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
1576
|
+
children: [
|
|
1577
|
+
/* @__PURE__ */ jsx14(
|
|
1578
|
+
"div",
|
|
1579
|
+
{
|
|
1580
|
+
style: { flex: 1, height: 1, background: "rgba(128,128,128,0.2)" }
|
|
1581
|
+
}
|
|
1582
|
+
),
|
|
1583
|
+
/* @__PURE__ */ jsx14(
|
|
1584
|
+
"span",
|
|
1585
|
+
{
|
|
1586
|
+
style: {
|
|
1587
|
+
fontSize: 12,
|
|
1588
|
+
fontWeight: 600,
|
|
1589
|
+
color: "rgba(128,128,128,0.7)",
|
|
1590
|
+
whiteSpace: "nowrap",
|
|
1591
|
+
userSelect: "none"
|
|
1592
|
+
},
|
|
1593
|
+
children: formatDate(date)
|
|
1594
|
+
}
|
|
1595
|
+
),
|
|
1596
|
+
/* @__PURE__ */ jsx14(
|
|
1597
|
+
"div",
|
|
1598
|
+
{
|
|
1599
|
+
style: { flex: 1, height: 1, background: "rgba(128,128,128,0.2)" }
|
|
1600
|
+
}
|
|
1601
|
+
)
|
|
1602
|
+
]
|
|
954
1603
|
}
|
|
955
1604
|
);
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
1605
|
+
|
|
1606
|
+
// src/react/components/EmptyStateIndicator/EmptyStateIndicator.tsx
|
|
1607
|
+
import { jsx as jsx15, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1608
|
+
var DEFAULT_TEXTS = {
|
|
1609
|
+
message: "No messages yet. Say hello! \u{1F44B}",
|
|
1610
|
+
room: "No conversations yet.",
|
|
1611
|
+
thread: "No replies yet.",
|
|
1612
|
+
search: "No results found."
|
|
1613
|
+
};
|
|
1614
|
+
var EmptyStateIndicator = ({
|
|
1615
|
+
listType = "message",
|
|
1616
|
+
text,
|
|
1617
|
+
className = ""
|
|
1618
|
+
}) => /* @__PURE__ */ jsxs5(
|
|
1619
|
+
"div",
|
|
1620
|
+
{
|
|
1621
|
+
className: `hermes-empty-state ${className}`,
|
|
1622
|
+
style: {
|
|
1623
|
+
display: "flex",
|
|
1624
|
+
flexDirection: "column",
|
|
1625
|
+
alignItems: "center",
|
|
1626
|
+
justifyContent: "center",
|
|
1627
|
+
gap: 8,
|
|
1628
|
+
padding: 32,
|
|
1629
|
+
textAlign: "center",
|
|
1630
|
+
opacity: 0.5,
|
|
1631
|
+
flex: 1
|
|
1632
|
+
},
|
|
1633
|
+
children: [
|
|
1634
|
+
/* @__PURE__ */ jsx15("span", { style: { fontSize: 36 }, children: listType === "message" ? "\u{1F4AC}" : listType === "room" ? "\u{1F4ED}" : listType === "thread" ? "\u{1F9F5}" : "\u{1F50D}" }),
|
|
1635
|
+
/* @__PURE__ */ jsx15("span", { style: { fontSize: 14 }, children: text || DEFAULT_TEXTS[listType] })
|
|
1636
|
+
]
|
|
1637
|
+
}
|
|
1638
|
+
);
|
|
1639
|
+
|
|
1640
|
+
// src/react/components/Loading/LoadingIndicator.tsx
|
|
1641
|
+
import { jsx as jsx16, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1642
|
+
var LoadingIndicator = ({
|
|
1643
|
+
size = 32,
|
|
1644
|
+
color = "#0084ff",
|
|
1645
|
+
text,
|
|
1646
|
+
className = ""
|
|
1647
|
+
}) => /* @__PURE__ */ jsxs6(
|
|
1648
|
+
"div",
|
|
1649
|
+
{
|
|
1650
|
+
className: `hermes-loading ${className}`,
|
|
1651
|
+
style: {
|
|
1652
|
+
display: "flex",
|
|
1653
|
+
flexDirection: "column",
|
|
1654
|
+
alignItems: "center",
|
|
1655
|
+
justifyContent: "center",
|
|
1656
|
+
gap: 8,
|
|
1657
|
+
padding: 16
|
|
1658
|
+
},
|
|
1659
|
+
children: [
|
|
1660
|
+
/* @__PURE__ */ jsx16(
|
|
1661
|
+
"div",
|
|
1662
|
+
{
|
|
1663
|
+
style: {
|
|
1664
|
+
width: size,
|
|
1665
|
+
height: size,
|
|
1666
|
+
border: `3px solid rgba(128,128,128,0.15)`,
|
|
1667
|
+
borderTopColor: color,
|
|
1668
|
+
borderRadius: "50%",
|
|
1669
|
+
animation: "hermes-spin 0.8s linear infinite"
|
|
1670
|
+
}
|
|
1671
|
+
}
|
|
1672
|
+
),
|
|
1673
|
+
text && /* @__PURE__ */ jsx16("span", { style: { fontSize: 13, opacity: 0.6 }, children: text }),
|
|
1674
|
+
/* @__PURE__ */ jsx16("style", { children: `
|
|
1675
|
+
@keyframes hermes-spin {
|
|
1676
|
+
to { transform: rotate(360deg); }
|
|
1677
|
+
}
|
|
1678
|
+
` })
|
|
1679
|
+
]
|
|
1680
|
+
}
|
|
1681
|
+
);
|
|
1682
|
+
var LoadingErrorIndicator = ({
|
|
1683
|
+
error,
|
|
1684
|
+
onRetry,
|
|
1685
|
+
className = ""
|
|
972
1686
|
}) => {
|
|
973
|
-
|
|
974
|
-
const
|
|
975
|
-
|
|
1687
|
+
if (!error) return null;
|
|
1688
|
+
const message = typeof error === "string" ? error : error.message;
|
|
1689
|
+
return /* @__PURE__ */ jsxs6(
|
|
1690
|
+
"div",
|
|
1691
|
+
{
|
|
1692
|
+
className: `hermes-loading-error ${className}`,
|
|
1693
|
+
style: {
|
|
1694
|
+
display: "flex",
|
|
1695
|
+
flexDirection: "column",
|
|
1696
|
+
alignItems: "center",
|
|
1697
|
+
justifyContent: "center",
|
|
1698
|
+
gap: 8,
|
|
1699
|
+
padding: 24,
|
|
1700
|
+
textAlign: "center"
|
|
1701
|
+
},
|
|
1702
|
+
children: [
|
|
1703
|
+
/* @__PURE__ */ jsx16("span", { style: { fontSize: 28 }, children: "\u26A0\uFE0F" }),
|
|
1704
|
+
/* @__PURE__ */ jsx16("span", { style: { fontSize: 14, opacity: 0.7 }, children: message }),
|
|
1705
|
+
onRetry && /* @__PURE__ */ jsx16(
|
|
1706
|
+
"button",
|
|
1707
|
+
{
|
|
1708
|
+
onClick: onRetry,
|
|
1709
|
+
style: {
|
|
1710
|
+
marginTop: 4,
|
|
1711
|
+
padding: "6px 16px",
|
|
1712
|
+
border: "1px solid rgba(128,128,128,0.3)",
|
|
1713
|
+
borderRadius: 8,
|
|
1714
|
+
background: "none",
|
|
1715
|
+
cursor: "pointer",
|
|
1716
|
+
fontSize: 13,
|
|
1717
|
+
fontWeight: 600
|
|
1718
|
+
},
|
|
1719
|
+
children: "Retry"
|
|
1720
|
+
}
|
|
1721
|
+
)
|
|
1722
|
+
]
|
|
1723
|
+
}
|
|
1724
|
+
);
|
|
1725
|
+
};
|
|
1726
|
+
|
|
1727
|
+
// src/react/components/TypingIndicator.tsx
|
|
1728
|
+
import { jsx as jsx17, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1729
|
+
var TypingIndicator = ({
|
|
1730
|
+
typingText,
|
|
1731
|
+
className = ""
|
|
1732
|
+
}) => {
|
|
1733
|
+
if (!typingText) return null;
|
|
1734
|
+
return /* @__PURE__ */ jsxs7(
|
|
1735
|
+
"div",
|
|
1736
|
+
{
|
|
1737
|
+
className: `hermes-typing-indicator ${className}`,
|
|
1738
|
+
style: {
|
|
1739
|
+
display: "flex",
|
|
1740
|
+
alignItems: "center",
|
|
1741
|
+
gap: 6,
|
|
1742
|
+
padding: "4px 16px",
|
|
1743
|
+
minHeight: 24
|
|
1744
|
+
},
|
|
1745
|
+
children: [
|
|
1746
|
+
/* @__PURE__ */ jsx17("div", { style: { display: "flex", gap: 3 }, children: [0, 1, 2].map((i) => /* @__PURE__ */ jsx17(
|
|
1747
|
+
"span",
|
|
1748
|
+
{
|
|
1749
|
+
style: {
|
|
1750
|
+
width: 6,
|
|
1751
|
+
height: 6,
|
|
1752
|
+
borderRadius: "50%",
|
|
1753
|
+
background: "#aaa",
|
|
1754
|
+
display: "block",
|
|
1755
|
+
animation: `hermes-bounce 1.2s ease-in-out ${i * 0.2}s infinite`
|
|
1756
|
+
}
|
|
1757
|
+
},
|
|
1758
|
+
i
|
|
1759
|
+
)) }),
|
|
1760
|
+
/* @__PURE__ */ jsx17("span", { style: { fontSize: 12, opacity: 0.6 }, children: typingText }),
|
|
1761
|
+
/* @__PURE__ */ jsx17("style", { children: `
|
|
1762
|
+
@keyframes hermes-bounce {
|
|
1763
|
+
0%, 80%, 100% { transform: translateY(0); }
|
|
1764
|
+
40% { transform: translateY(-4px); }
|
|
1765
|
+
}
|
|
1766
|
+
` })
|
|
1767
|
+
]
|
|
1768
|
+
}
|
|
1769
|
+
);
|
|
1770
|
+
};
|
|
1771
|
+
|
|
1772
|
+
// src/react/components/MessageList.tsx
|
|
1773
|
+
import { Fragment, jsx as jsx18, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1774
|
+
var isSameDay = (d1, d2) => {
|
|
1775
|
+
const a = new Date(d1);
|
|
1776
|
+
const b = new Date(d2);
|
|
1777
|
+
return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
|
|
1778
|
+
};
|
|
1779
|
+
var MessageList = (props) => {
|
|
1780
|
+
const chatCtx = useChatContext("MessageList");
|
|
1781
|
+
const roomStateCtx = useRoomStateContext("MessageList");
|
|
1782
|
+
const roomActionCtx = useRoomActionContext("MessageList");
|
|
1783
|
+
const typingCtx = useTypingContext("MessageList");
|
|
1784
|
+
const componentCtx = useComponentContext("MessageList");
|
|
1785
|
+
const messages = props.messages ?? roomStateCtx.messages ?? [];
|
|
1786
|
+
const currentUser = props.currentUser ?? chatCtx.currentUser;
|
|
1787
|
+
const loading = props.loading ?? roomStateCtx.loading ?? false;
|
|
1788
|
+
const loadingMore = props.loadingMore ?? roomStateCtx.loadingMore ?? false;
|
|
1789
|
+
const hasMore = props.hasMore ?? roomStateCtx.hasMore ?? false;
|
|
1790
|
+
const onLoadMore = props.onLoadMore ?? roomActionCtx.loadMore;
|
|
1791
|
+
const onEdit = props.onEdit ?? (roomActionCtx.editMessage ? (id, text) => roomActionCtx.editMessage(id, text) : void 0);
|
|
1792
|
+
const onDelete = props.onDelete ?? (roomActionCtx.deleteMessage ? (id) => roomActionCtx.deleteMessage(id) : void 0);
|
|
1793
|
+
const onReact = props.onReact ?? (roomActionCtx.addReaction ? (id, emoji) => roomActionCtx.addReaction(id, emoji) : void 0);
|
|
1794
|
+
const onReply = props.onReply;
|
|
1795
|
+
const onOpenThread = props.onOpenThread ?? (roomActionCtx.openThread ? (msg) => roomActionCtx.openThread(msg) : void 0);
|
|
1796
|
+
const autoScroll = props.autoScroll ?? true;
|
|
1797
|
+
const disableDateSeparator = props.disableDateSeparator ?? false;
|
|
1798
|
+
const className = props.className ?? "";
|
|
1799
|
+
const renderMessage = props.renderMessage;
|
|
1800
|
+
const renderAvatar = props.renderAvatar;
|
|
1801
|
+
const typingText = props.typingText ?? typingCtx.typingText ?? null;
|
|
1802
|
+
const MessageComponent = componentCtx.Message || Message;
|
|
1803
|
+
const DateSepComponent = componentCtx.DateSeparator || DateSeparator;
|
|
1804
|
+
const EmptyComponent = componentCtx.EmptyStateIndicator || EmptyStateIndicator;
|
|
1805
|
+
const LoadingComponent = componentCtx.LoadingIndicator || LoadingIndicator;
|
|
1806
|
+
const TypingComponent = componentCtx.TypingIndicator || TypingIndicator;
|
|
1807
|
+
const bottomRef = useRef6(null);
|
|
1808
|
+
const containerRef = useRef6(null);
|
|
1809
|
+
useEffect9(() => {
|
|
976
1810
|
if (autoScroll && bottomRef.current) {
|
|
977
1811
|
bottomRef.current.scrollIntoView({ behavior: "smooth" });
|
|
978
1812
|
}
|
|
979
1813
|
}, [messages, autoScroll]);
|
|
980
|
-
|
|
1814
|
+
useEffect9(() => {
|
|
981
1815
|
const container = containerRef.current;
|
|
982
1816
|
if (!container || !onLoadMore) return;
|
|
983
1817
|
const onScroll = () => {
|
|
@@ -987,21 +1821,33 @@ var MessageList = ({
|
|
|
987
1821
|
return () => container.removeEventListener("scroll", onScroll);
|
|
988
1822
|
}, [hasMore, loadingMore, onLoadMore]);
|
|
989
1823
|
if (loading) {
|
|
990
|
-
return /* @__PURE__ */
|
|
1824
|
+
return /* @__PURE__ */ jsx18(
|
|
991
1825
|
"div",
|
|
992
1826
|
{
|
|
993
1827
|
style: {
|
|
994
1828
|
display: "flex",
|
|
995
1829
|
alignItems: "center",
|
|
996
1830
|
justifyContent: "center",
|
|
997
|
-
height: "100%"
|
|
1831
|
+
height: "100%",
|
|
1832
|
+
flex: 1
|
|
998
1833
|
},
|
|
999
|
-
children: "Loading messages..."
|
|
1834
|
+
children: /* @__PURE__ */ jsx18(LoadingComponent, { text: "Loading messages..." })
|
|
1000
1835
|
}
|
|
1001
1836
|
);
|
|
1002
1837
|
}
|
|
1003
|
-
|
|
1004
|
-
|
|
1838
|
+
const getGroupStyle = (index) => {
|
|
1839
|
+
const msg = messages[index];
|
|
1840
|
+
const prev = index > 0 ? messages[index - 1] : null;
|
|
1841
|
+
const next = index < messages.length - 1 ? messages[index + 1] : null;
|
|
1842
|
+
const sameSenderPrev = prev && prev.senderId === msg.senderId && !prev.isDeleted && isSameDay(prev.createdAt, msg.createdAt);
|
|
1843
|
+
const sameSenderNext = next && next.senderId === msg.senderId && !next.isDeleted && isSameDay(next.createdAt, msg.createdAt);
|
|
1844
|
+
if (sameSenderPrev && sameSenderNext) return "middle";
|
|
1845
|
+
if (sameSenderPrev) return "bottom";
|
|
1846
|
+
if (sameSenderNext) return "top";
|
|
1847
|
+
return "single";
|
|
1848
|
+
};
|
|
1849
|
+
return /* @__PURE__ */ jsxs8(Fragment, { children: [
|
|
1850
|
+
/* @__PURE__ */ jsx18("style", { children: `
|
|
1005
1851
|
@keyframes hermes-bounce {
|
|
1006
1852
|
0%, 80%, 100% { transform: translateY(0); }
|
|
1007
1853
|
40% { transform: translateY(-5px); }
|
|
@@ -1011,7 +1857,7 @@ var MessageList = ({
|
|
|
1011
1857
|
to { opacity: 1; transform: scale(1); }
|
|
1012
1858
|
}
|
|
1013
1859
|
` }),
|
|
1014
|
-
/* @__PURE__ */
|
|
1860
|
+
/* @__PURE__ */ jsxs8(
|
|
1015
1861
|
"div",
|
|
1016
1862
|
{
|
|
1017
1863
|
ref: containerRef,
|
|
@@ -1020,11 +1866,11 @@ var MessageList = ({
|
|
|
1020
1866
|
overflowY: "auto",
|
|
1021
1867
|
display: "flex",
|
|
1022
1868
|
flexDirection: "column",
|
|
1023
|
-
|
|
1869
|
+
flex: 1,
|
|
1024
1870
|
padding: "16px"
|
|
1025
1871
|
},
|
|
1026
1872
|
children: [
|
|
1027
|
-
hasMore && /* @__PURE__ */
|
|
1873
|
+
hasMore && /* @__PURE__ */ jsx18("div", { style: { textAlign: "center", marginBottom: 12 }, children: loadingMore ? /* @__PURE__ */ jsx18(LoadingComponent, { size: 20, text: "Loading older messages..." }) : /* @__PURE__ */ jsx18(
|
|
1028
1874
|
"button",
|
|
1029
1875
|
{
|
|
1030
1876
|
onClick: onLoadMore,
|
|
@@ -1039,35 +1885,32 @@ var MessageList = ({
|
|
|
1039
1885
|
children: "Load older messages"
|
|
1040
1886
|
}
|
|
1041
1887
|
) }),
|
|
1042
|
-
messages.length === 0 && /* @__PURE__ */
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
renderAvatar
|
|
1066
|
-
}
|
|
1067
|
-
) }, message._id);
|
|
1888
|
+
messages.length === 0 && /* @__PURE__ */ jsx18(EmptyComponent, { listType: "message" }),
|
|
1889
|
+
messages.map((message, index) => {
|
|
1890
|
+
const isOwn = message.senderId === currentUser?.userId;
|
|
1891
|
+
const groupStyle = getGroupStyle(index);
|
|
1892
|
+
const showDateSep = !disableDateSeparator && (index === 0 || !isSameDay(messages[index - 1].createdAt, message.createdAt));
|
|
1893
|
+
return /* @__PURE__ */ jsxs8(React10.Fragment, { children: [
|
|
1894
|
+
showDateSep && /* @__PURE__ */ jsx18(DateSepComponent, { date: new Date(message.createdAt) }),
|
|
1895
|
+
/* @__PURE__ */ jsx18("div", { style: { marginBottom: groupStyle === "bottom" || groupStyle === "single" ? 8 : 2 }, children: renderMessage ? renderMessage(message, isOwn) : /* @__PURE__ */ jsx18(
|
|
1896
|
+
MessageComponent,
|
|
1897
|
+
{
|
|
1898
|
+
message,
|
|
1899
|
+
isOwn,
|
|
1900
|
+
onEdit,
|
|
1901
|
+
onDelete,
|
|
1902
|
+
onReact,
|
|
1903
|
+
onReply,
|
|
1904
|
+
onOpenThread,
|
|
1905
|
+
renderAvatar,
|
|
1906
|
+
groupStyle,
|
|
1907
|
+
showAvatar: true
|
|
1908
|
+
}
|
|
1909
|
+
) })
|
|
1910
|
+
] }, message._id);
|
|
1068
1911
|
}),
|
|
1069
|
-
/* @__PURE__ */
|
|
1070
|
-
/* @__PURE__ */
|
|
1912
|
+
typingText && /* @__PURE__ */ jsx18(TypingComponent, { typingText }),
|
|
1913
|
+
/* @__PURE__ */ jsx18("div", { ref: bottomRef })
|
|
1071
1914
|
]
|
|
1072
1915
|
}
|
|
1073
1916
|
)
|
|
@@ -1075,28 +1918,34 @@ var MessageList = ({
|
|
|
1075
1918
|
};
|
|
1076
1919
|
|
|
1077
1920
|
// src/react/components/ChatInput.tsx
|
|
1078
|
-
import { useState as
|
|
1079
|
-
import { Fragment as Fragment2, jsx as
|
|
1080
|
-
var ChatInput = ({
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1921
|
+
import { useState as useState10, useRef as useRef7, useCallback as useCallback10 } from "react";
|
|
1922
|
+
import { Fragment as Fragment2, jsx as jsx19, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1923
|
+
var ChatInput = (props) => {
|
|
1924
|
+
const roomActionCtx = useRoomActionContext("ChatInput");
|
|
1925
|
+
const typingCtx = useTypingContext("ChatInput");
|
|
1926
|
+
const chatCtx = useChatContext("ChatInput");
|
|
1927
|
+
const onSendText = props.onSendText ?? (roomActionCtx.sendMessage ? async (text2) => {
|
|
1928
|
+
await roomActionCtx.sendMessage({ type: "text", text: text2 });
|
|
1929
|
+
} : void 0);
|
|
1930
|
+
const onSendFile = props.onSendFile;
|
|
1931
|
+
const onTypingStart = props.onTypingStart ?? typingCtx.startTyping;
|
|
1932
|
+
const onTypingStop = props.onTypingStop ?? typingCtx.stopTyping;
|
|
1933
|
+
const {
|
|
1934
|
+
replyingTo,
|
|
1935
|
+
onCancelReply,
|
|
1936
|
+
disabled = false,
|
|
1937
|
+
placeholder = "Type a message...",
|
|
1938
|
+
maxLength = 4e3,
|
|
1939
|
+
className = "",
|
|
1940
|
+
inputClassName = "",
|
|
1941
|
+
renderAttachIcon,
|
|
1942
|
+
renderSendIcon
|
|
1943
|
+
} = props;
|
|
1944
|
+
const [text, setText] = useState10("");
|
|
1945
|
+
const [sending, setSending] = useState10(false);
|
|
1946
|
+
const fileRef = useRef7(null);
|
|
1947
|
+
const textareaRef = useRef7(null);
|
|
1948
|
+
const resizeTextarea = useCallback10(() => {
|
|
1100
1949
|
const el = textareaRef.current;
|
|
1101
1950
|
if (!el) return;
|
|
1102
1951
|
el.style.height = "auto";
|
|
@@ -1109,7 +1958,7 @@ var ChatInput = ({
|
|
|
1109
1958
|
};
|
|
1110
1959
|
const handleSend = async () => {
|
|
1111
1960
|
const trimmed = text.trim();
|
|
1112
|
-
if (!trimmed || sending || disabled) return;
|
|
1961
|
+
if (!trimmed || sending || disabled || !onSendText) return;
|
|
1113
1962
|
setSending(true);
|
|
1114
1963
|
try {
|
|
1115
1964
|
await onSendText(trimmed);
|
|
@@ -1132,7 +1981,7 @@ var ChatInput = ({
|
|
|
1132
1981
|
await onSendFile(file);
|
|
1133
1982
|
if (fileRef.current) fileRef.current.value = "";
|
|
1134
1983
|
};
|
|
1135
|
-
return /* @__PURE__ */
|
|
1984
|
+
return /* @__PURE__ */ jsxs9(
|
|
1136
1985
|
"div",
|
|
1137
1986
|
{
|
|
1138
1987
|
className: `hermes-chat-input ${className}`,
|
|
@@ -1143,7 +1992,7 @@ var ChatInput = ({
|
|
|
1143
1992
|
borderTop: "1px solid #e0e0e0"
|
|
1144
1993
|
},
|
|
1145
1994
|
children: [
|
|
1146
|
-
replyingTo && /* @__PURE__ */
|
|
1995
|
+
replyingTo && /* @__PURE__ */ jsxs9(
|
|
1147
1996
|
"div",
|
|
1148
1997
|
{
|
|
1149
1998
|
className: "hermes-chat-input__reply",
|
|
@@ -1159,11 +2008,11 @@ var ChatInput = ({
|
|
|
1159
2008
|
fontSize: 12
|
|
1160
2009
|
},
|
|
1161
2010
|
children: [
|
|
1162
|
-
/* @__PURE__ */
|
|
1163
|
-
/* @__PURE__ */
|
|
1164
|
-
/* @__PURE__ */
|
|
2011
|
+
/* @__PURE__ */ jsxs9("div", { style: { overflow: "hidden" }, children: [
|
|
2012
|
+
/* @__PURE__ */ jsx19("span", { style: { fontWeight: 600, marginRight: 4 }, children: "Replying to:" }),
|
|
2013
|
+
/* @__PURE__ */ jsx19("span", { style: { opacity: 0.7 }, children: replyingTo.type === "text" ? replyingTo.text?.slice(0, 60) : `[${replyingTo.type}]` })
|
|
1165
2014
|
] }),
|
|
1166
|
-
/* @__PURE__ */
|
|
2015
|
+
/* @__PURE__ */ jsx19(
|
|
1167
2016
|
"button",
|
|
1168
2017
|
{
|
|
1169
2018
|
onClick: onCancelReply,
|
|
@@ -1180,14 +2029,14 @@ var ChatInput = ({
|
|
|
1180
2029
|
]
|
|
1181
2030
|
}
|
|
1182
2031
|
),
|
|
1183
|
-
/* @__PURE__ */
|
|
2032
|
+
/* @__PURE__ */ jsxs9(
|
|
1184
2033
|
"div",
|
|
1185
2034
|
{
|
|
1186
2035
|
className: "hermes-chat-input__row",
|
|
1187
2036
|
style: { display: "flex", alignItems: "flex-end", gap: 8 },
|
|
1188
2037
|
children: [
|
|
1189
|
-
onSendFile && /* @__PURE__ */
|
|
1190
|
-
/* @__PURE__ */
|
|
2038
|
+
onSendFile && /* @__PURE__ */ jsxs9(Fragment2, { children: [
|
|
2039
|
+
/* @__PURE__ */ jsx19(
|
|
1191
2040
|
"button",
|
|
1192
2041
|
{
|
|
1193
2042
|
onClick: () => fileRef.current?.click(),
|
|
@@ -1201,23 +2050,10 @@ var ChatInput = ({
|
|
|
1201
2050
|
flexShrink: 0,
|
|
1202
2051
|
opacity: disabled ? 0.4 : 1
|
|
1203
2052
|
},
|
|
1204
|
-
children: renderAttachIcon ? renderAttachIcon() : /* @__PURE__ */
|
|
1205
|
-
"svg",
|
|
1206
|
-
{
|
|
1207
|
-
width: "20",
|
|
1208
|
-
height: "20",
|
|
1209
|
-
viewBox: "0 0 24 24",
|
|
1210
|
-
fill: "none",
|
|
1211
|
-
stroke: "currentColor",
|
|
1212
|
-
strokeWidth: "2",
|
|
1213
|
-
strokeLinecap: "round",
|
|
1214
|
-
strokeLinejoin: "round",
|
|
1215
|
-
children: /* @__PURE__ */ jsx2("path", { d: "m21.44 11.05-9.19 9.19a6 6 0 0 1-8.49-8.49l8.57-8.57A4 4 0 1 1 18 8.84l-8.59 8.57a2 2 0 0 1-2.83-2.83l8.49-8.48" })
|
|
1216
|
-
}
|
|
1217
|
-
)
|
|
2053
|
+
children: renderAttachIcon ? renderAttachIcon() : /* @__PURE__ */ jsx19("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx19("path", { d: "m21.44 11.05-9.19 9.19a6 6 0 0 1-8.49-8.49l8.57-8.57A4 4 0 1 1 18 8.84l-8.59 8.57a2 2 0 0 1-2.83-2.83l8.49-8.48" }) })
|
|
1218
2054
|
}
|
|
1219
2055
|
),
|
|
1220
|
-
/* @__PURE__ */
|
|
2056
|
+
/* @__PURE__ */ jsx19(
|
|
1221
2057
|
"input",
|
|
1222
2058
|
{
|
|
1223
2059
|
ref: fileRef,
|
|
@@ -1228,7 +2064,7 @@ var ChatInput = ({
|
|
|
1228
2064
|
}
|
|
1229
2065
|
)
|
|
1230
2066
|
] }),
|
|
1231
|
-
/* @__PURE__ */
|
|
2067
|
+
/* @__PURE__ */ jsx19(
|
|
1232
2068
|
"textarea",
|
|
1233
2069
|
{
|
|
1234
2070
|
ref: textareaRef,
|
|
@@ -1255,7 +2091,7 @@ var ChatInput = ({
|
|
|
1255
2091
|
}
|
|
1256
2092
|
}
|
|
1257
2093
|
),
|
|
1258
|
-
/* @__PURE__ */
|
|
2094
|
+
/* @__PURE__ */ jsx19(
|
|
1259
2095
|
"button",
|
|
1260
2096
|
{
|
|
1261
2097
|
onClick: handleSend,
|
|
@@ -1269,35 +2105,24 @@ var ChatInput = ({
|
|
|
1269
2105
|
flexShrink: 0,
|
|
1270
2106
|
opacity: !text.trim() || sending || disabled ? 0.4 : 1
|
|
1271
2107
|
},
|
|
1272
|
-
children: renderSendIcon ? renderSendIcon() : /* @__PURE__ */
|
|
2108
|
+
children: renderSendIcon ? renderSendIcon() : /* @__PURE__ */ jsx19("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsx19("path", { d: "M2.01 21L23 12 2.01 3 2 10l15 2-15 2z" }) })
|
|
1273
2109
|
}
|
|
1274
2110
|
)
|
|
1275
2111
|
]
|
|
1276
2112
|
}
|
|
1277
2113
|
),
|
|
1278
|
-
text.length > maxLength * 0.8 && /* @__PURE__ */
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
textAlign: "right",
|
|
1284
|
-
opacity: 0.5,
|
|
1285
|
-
marginTop: 2
|
|
1286
|
-
},
|
|
1287
|
-
children: [
|
|
1288
|
-
text.length,
|
|
1289
|
-
"/",
|
|
1290
|
-
maxLength
|
|
1291
|
-
]
|
|
1292
|
-
}
|
|
1293
|
-
)
|
|
2114
|
+
text.length > maxLength * 0.8 && /* @__PURE__ */ jsxs9("div", { style: { fontSize: 10, textAlign: "right", opacity: 0.5, marginTop: 2 }, children: [
|
|
2115
|
+
text.length,
|
|
2116
|
+
"/",
|
|
2117
|
+
maxLength
|
|
2118
|
+
] })
|
|
1294
2119
|
]
|
|
1295
2120
|
}
|
|
1296
2121
|
);
|
|
1297
2122
|
};
|
|
1298
2123
|
|
|
1299
2124
|
// src/react/components/RoomList.tsx
|
|
1300
|
-
import { jsx as
|
|
2125
|
+
import { jsx as jsx20, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1301
2126
|
var formatLastActivity = (iso) => {
|
|
1302
2127
|
const date = new Date(iso);
|
|
1303
2128
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -1328,7 +2153,7 @@ var getLastMessagePreview = (room) => {
|
|
|
1328
2153
|
if (msg.type === "link") return `\u{1F517} ${msg.url}`;
|
|
1329
2154
|
return "";
|
|
1330
2155
|
};
|
|
1331
|
-
var DefaultRoomItem = ({ room, isActive, currentUserId, renderAvatar, itemClassName }) => /* @__PURE__ */
|
|
2156
|
+
var DefaultRoomItem = ({ room, isActive, currentUserId, renderAvatar, itemClassName }) => /* @__PURE__ */ jsxs10(
|
|
1332
2157
|
"div",
|
|
1333
2158
|
{
|
|
1334
2159
|
className: `hermes-room-item ${isActive ? "hermes-room-item--active" : ""} ${itemClassName ?? ""}`,
|
|
@@ -1342,7 +2167,7 @@ var DefaultRoomItem = ({ room, isActive, currentUserId, renderAvatar, itemClassN
|
|
|
1342
2167
|
borderLeft: isActive ? "3px solid #0084ff" : "3px solid transparent"
|
|
1343
2168
|
},
|
|
1344
2169
|
children: [
|
|
1345
|
-
/* @__PURE__ */
|
|
2170
|
+
/* @__PURE__ */ jsx20("div", { style: { flexShrink: 0 }, children: renderAvatar ? renderAvatar(room) : /* @__PURE__ */ jsx20(
|
|
1346
2171
|
"div",
|
|
1347
2172
|
{
|
|
1348
2173
|
style: {
|
|
@@ -1359,8 +2184,8 @@ var DefaultRoomItem = ({ room, isActive, currentUserId, renderAvatar, itemClassN
|
|
|
1359
2184
|
children: room.type === "group" ? "G" : "D"
|
|
1360
2185
|
}
|
|
1361
2186
|
) }),
|
|
1362
|
-
/* @__PURE__ */
|
|
1363
|
-
/* @__PURE__ */
|
|
2187
|
+
/* @__PURE__ */ jsxs10("div", { style: { flex: 1, overflow: "hidden" }, children: [
|
|
2188
|
+
/* @__PURE__ */ jsxs10(
|
|
1364
2189
|
"div",
|
|
1365
2190
|
{
|
|
1366
2191
|
style: {
|
|
@@ -1369,7 +2194,7 @@ var DefaultRoomItem = ({ room, isActive, currentUserId, renderAvatar, itemClassN
|
|
|
1369
2194
|
alignItems: "baseline"
|
|
1370
2195
|
},
|
|
1371
2196
|
children: [
|
|
1372
|
-
/* @__PURE__ */
|
|
2197
|
+
/* @__PURE__ */ jsx20(
|
|
1373
2198
|
"span",
|
|
1374
2199
|
{
|
|
1375
2200
|
style: {
|
|
@@ -1382,7 +2207,7 @@ var DefaultRoomItem = ({ room, isActive, currentUserId, renderAvatar, itemClassN
|
|
|
1382
2207
|
children: getRoomName(room, currentUserId)
|
|
1383
2208
|
}
|
|
1384
2209
|
),
|
|
1385
|
-
/* @__PURE__ */
|
|
2210
|
+
/* @__PURE__ */ jsx20(
|
|
1386
2211
|
"span",
|
|
1387
2212
|
{
|
|
1388
2213
|
style: { fontSize: 11, opacity: 0.5, flexShrink: 0, marginLeft: 4 },
|
|
@@ -1392,7 +2217,7 @@ var DefaultRoomItem = ({ room, isActive, currentUserId, renderAvatar, itemClassN
|
|
|
1392
2217
|
]
|
|
1393
2218
|
}
|
|
1394
2219
|
),
|
|
1395
|
-
/* @__PURE__ */
|
|
2220
|
+
/* @__PURE__ */ jsxs10(
|
|
1396
2221
|
"div",
|
|
1397
2222
|
{
|
|
1398
2223
|
style: {
|
|
@@ -1402,7 +2227,7 @@ var DefaultRoomItem = ({ room, isActive, currentUserId, renderAvatar, itemClassN
|
|
|
1402
2227
|
marginTop: 2
|
|
1403
2228
|
},
|
|
1404
2229
|
children: [
|
|
1405
|
-
/* @__PURE__ */
|
|
2230
|
+
/* @__PURE__ */ jsx20(
|
|
1406
2231
|
"span",
|
|
1407
2232
|
{
|
|
1408
2233
|
style: {
|
|
@@ -1415,7 +2240,7 @@ var DefaultRoomItem = ({ room, isActive, currentUserId, renderAvatar, itemClassN
|
|
|
1415
2240
|
children: getLastMessagePreview(room)
|
|
1416
2241
|
}
|
|
1417
2242
|
),
|
|
1418
|
-
room.unreadCount > 0 && /* @__PURE__ */
|
|
2243
|
+
room.unreadCount > 0 && /* @__PURE__ */ jsx20(
|
|
1419
2244
|
"span",
|
|
1420
2245
|
{
|
|
1421
2246
|
style: {
|
|
@@ -1452,7 +2277,7 @@ var RoomList = ({
|
|
|
1452
2277
|
className = "",
|
|
1453
2278
|
itemClassName = ""
|
|
1454
2279
|
}) => {
|
|
1455
|
-
return /* @__PURE__ */
|
|
2280
|
+
return /* @__PURE__ */ jsxs10(
|
|
1456
2281
|
"div",
|
|
1457
2282
|
{
|
|
1458
2283
|
className: `hermes-room-list ${className}`,
|
|
@@ -1463,7 +2288,7 @@ var RoomList = ({
|
|
|
1463
2288
|
overflowY: "auto"
|
|
1464
2289
|
},
|
|
1465
2290
|
children: [
|
|
1466
|
-
(onCreateDirect || onCreateGroup) && /* @__PURE__ */
|
|
2291
|
+
(onCreateDirect || onCreateGroup) && /* @__PURE__ */ jsxs10(
|
|
1467
2292
|
"div",
|
|
1468
2293
|
{
|
|
1469
2294
|
style: {
|
|
@@ -1473,7 +2298,7 @@ var RoomList = ({
|
|
|
1473
2298
|
borderBottom: "1px solid #e0e0e0"
|
|
1474
2299
|
},
|
|
1475
2300
|
children: [
|
|
1476
|
-
onCreateDirect && /* @__PURE__ */
|
|
2301
|
+
onCreateDirect && /* @__PURE__ */ jsx20(
|
|
1477
2302
|
"button",
|
|
1478
2303
|
{
|
|
1479
2304
|
onClick: onCreateDirect,
|
|
@@ -1491,7 +2316,7 @@ var RoomList = ({
|
|
|
1491
2316
|
children: "+ Direct"
|
|
1492
2317
|
}
|
|
1493
2318
|
),
|
|
1494
|
-
onCreateGroup && /* @__PURE__ */
|
|
2319
|
+
onCreateGroup && /* @__PURE__ */ jsx20(
|
|
1495
2320
|
"button",
|
|
1496
2321
|
{
|
|
1497
2322
|
onClick: onCreateGroup,
|
|
@@ -1511,8 +2336,8 @@ var RoomList = ({
|
|
|
1511
2336
|
]
|
|
1512
2337
|
}
|
|
1513
2338
|
),
|
|
1514
|
-
loading && /* @__PURE__ */
|
|
1515
|
-
!loading && rooms.length === 0 && /* @__PURE__ */
|
|
2339
|
+
loading && /* @__PURE__ */ jsx20("div", { style: { padding: "12px 16px", opacity: 0.5, fontSize: 13 }, children: "Loading rooms..." }),
|
|
2340
|
+
!loading && rooms.length === 0 && /* @__PURE__ */ jsx20(
|
|
1516
2341
|
"div",
|
|
1517
2342
|
{
|
|
1518
2343
|
style: {
|
|
@@ -1526,7 +2351,7 @@ var RoomList = ({
|
|
|
1526
2351
|
),
|
|
1527
2352
|
!loading && rooms.map((room) => {
|
|
1528
2353
|
const isActive = room._id === activeRoomId;
|
|
1529
|
-
return /* @__PURE__ */
|
|
2354
|
+
return /* @__PURE__ */ jsx20("div", { onClick: () => onSelectRoom(room), children: renderRoomItem ? renderRoomItem(room, isActive) : /* @__PURE__ */ jsx20(
|
|
1530
2355
|
DefaultRoomItem,
|
|
1531
2356
|
{
|
|
1532
2357
|
room,
|
|
@@ -1542,58 +2367,13 @@ var RoomList = ({
|
|
|
1542
2367
|
);
|
|
1543
2368
|
};
|
|
1544
2369
|
|
|
1545
|
-
// src/react/components/TypingIndicator.tsx
|
|
1546
|
-
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1547
|
-
var TypingIndicator2 = ({
|
|
1548
|
-
typingText,
|
|
1549
|
-
className = ""
|
|
1550
|
-
}) => {
|
|
1551
|
-
if (!typingText) return null;
|
|
1552
|
-
return /* @__PURE__ */ jsxs4(
|
|
1553
|
-
"div",
|
|
1554
|
-
{
|
|
1555
|
-
className: `hermes-typing-indicator ${className}`,
|
|
1556
|
-
style: {
|
|
1557
|
-
display: "flex",
|
|
1558
|
-
alignItems: "center",
|
|
1559
|
-
gap: 6,
|
|
1560
|
-
padding: "4px 16px",
|
|
1561
|
-
minHeight: 24
|
|
1562
|
-
},
|
|
1563
|
-
children: [
|
|
1564
|
-
/* @__PURE__ */ jsx4("div", { style: { display: "flex", gap: 3 }, children: [0, 1, 2].map((i) => /* @__PURE__ */ jsx4(
|
|
1565
|
-
"span",
|
|
1566
|
-
{
|
|
1567
|
-
style: {
|
|
1568
|
-
width: 6,
|
|
1569
|
-
height: 6,
|
|
1570
|
-
borderRadius: "50%",
|
|
1571
|
-
background: "#aaa",
|
|
1572
|
-
display: "block",
|
|
1573
|
-
animation: `hermes-bounce 1.2s ease-in-out ${i * 0.2}s infinite`
|
|
1574
|
-
}
|
|
1575
|
-
},
|
|
1576
|
-
i
|
|
1577
|
-
)) }),
|
|
1578
|
-
/* @__PURE__ */ jsx4("span", { style: { fontSize: 12, opacity: 0.6 }, children: typingText }),
|
|
1579
|
-
/* @__PURE__ */ jsx4("style", { children: `
|
|
1580
|
-
@keyframes hermes-bounce {
|
|
1581
|
-
0%, 80%, 100% { transform: translateY(0); }
|
|
1582
|
-
40% { transform: translateY(-4px); }
|
|
1583
|
-
}
|
|
1584
|
-
` })
|
|
1585
|
-
]
|
|
1586
|
-
}
|
|
1587
|
-
);
|
|
1588
|
-
};
|
|
1589
|
-
|
|
1590
2370
|
// src/react/components/OnlineBadge.tsx
|
|
1591
|
-
import { jsx as
|
|
2371
|
+
import { jsx as jsx21 } from "react/jsx-runtime";
|
|
1592
2372
|
var OnlineBadge = ({
|
|
1593
2373
|
isOnline,
|
|
1594
2374
|
size = 10,
|
|
1595
2375
|
className = ""
|
|
1596
|
-
}) => /* @__PURE__ */
|
|
2376
|
+
}) => /* @__PURE__ */ jsx21(
|
|
1597
2377
|
"span",
|
|
1598
2378
|
{
|
|
1599
2379
|
className: `hermes-online-badge ${isOnline ? "hermes-online-badge--online" : "hermes-online-badge--offline"} ${className}`,
|
|
@@ -1611,9 +2391,9 @@ var OnlineBadge = ({
|
|
|
1611
2391
|
);
|
|
1612
2392
|
|
|
1613
2393
|
// src/react/components/ReactionPicker.tsx
|
|
1614
|
-
import { useState as
|
|
1615
|
-
import
|
|
1616
|
-
import { jsx as
|
|
2394
|
+
import { useState as useState11, useRef as useRef8, useEffect as useEffect10 } from "react";
|
|
2395
|
+
import EmojiPicker, { Theme } from "emoji-picker-react";
|
|
2396
|
+
import { jsx as jsx22, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
1617
2397
|
var DEFAULT_EMOJIS = ["\u{1F44D}", "\u2764\uFE0F", "\u{1F602}", "\u{1F62E}", "\u{1F622}", "\u{1F525}", "\u{1F389}", "\u{1F44F}"];
|
|
1618
2398
|
var ReactionPicker = ({
|
|
1619
2399
|
onSelect,
|
|
@@ -1623,8 +2403,8 @@ var ReactionPicker = ({
|
|
|
1623
2403
|
className = "",
|
|
1624
2404
|
align = "left"
|
|
1625
2405
|
}) => {
|
|
1626
|
-
const [showPicker, setShowPicker] =
|
|
1627
|
-
const containerRef =
|
|
2406
|
+
const [showPicker, setShowPicker] = useState11(false);
|
|
2407
|
+
const containerRef = useRef8(null);
|
|
1628
2408
|
const hasReacted = (emoji) => {
|
|
1629
2409
|
if (!currentUserId) return false;
|
|
1630
2410
|
return currentReactions.find((r) => r.emoji === emoji)?.users.includes(currentUserId) ?? false;
|
|
@@ -1633,7 +2413,7 @@ var ReactionPicker = ({
|
|
|
1633
2413
|
onSelect(emojiData.emoji);
|
|
1634
2414
|
setShowPicker(false);
|
|
1635
2415
|
};
|
|
1636
|
-
|
|
2416
|
+
useEffect10(() => {
|
|
1637
2417
|
const handleOutsideClick = (e) => {
|
|
1638
2418
|
if (!containerRef.current) return;
|
|
1639
2419
|
const target = e.target;
|
|
@@ -1646,14 +2426,14 @@ var ReactionPicker = ({
|
|
|
1646
2426
|
}
|
|
1647
2427
|
return () => window.removeEventListener("click", handleOutsideClick);
|
|
1648
2428
|
}, [showPicker]);
|
|
1649
|
-
return /* @__PURE__ */
|
|
2429
|
+
return /* @__PURE__ */ jsxs11(
|
|
1650
2430
|
"div",
|
|
1651
2431
|
{
|
|
1652
2432
|
ref: containerRef,
|
|
1653
2433
|
style: { position: "relative", display: "inline-block" },
|
|
1654
2434
|
className,
|
|
1655
2435
|
children: [
|
|
1656
|
-
/* @__PURE__ */
|
|
2436
|
+
/* @__PURE__ */ jsxs11(
|
|
1657
2437
|
"div",
|
|
1658
2438
|
{
|
|
1659
2439
|
style: {
|
|
@@ -1666,7 +2446,7 @@ var ReactionPicker = ({
|
|
|
1666
2446
|
border: "1px solid rgba(255,255,255,0.08)"
|
|
1667
2447
|
},
|
|
1668
2448
|
children: [
|
|
1669
|
-
emojis.map((emoji) => /* @__PURE__ */
|
|
2449
|
+
emojis.map((emoji) => /* @__PURE__ */ jsx22(
|
|
1670
2450
|
"button",
|
|
1671
2451
|
{
|
|
1672
2452
|
onClick: () => onSelect(emoji),
|
|
@@ -1686,7 +2466,7 @@ var ReactionPicker = ({
|
|
|
1686
2466
|
},
|
|
1687
2467
|
emoji
|
|
1688
2468
|
)),
|
|
1689
|
-
/* @__PURE__ */
|
|
2469
|
+
/* @__PURE__ */ jsx22(
|
|
1690
2470
|
"button",
|
|
1691
2471
|
{
|
|
1692
2472
|
onClick: (e) => {
|
|
@@ -1707,7 +2487,7 @@ var ReactionPicker = ({
|
|
|
1707
2487
|
]
|
|
1708
2488
|
}
|
|
1709
2489
|
),
|
|
1710
|
-
showPicker && /* @__PURE__ */
|
|
2490
|
+
showPicker && /* @__PURE__ */ jsx22(
|
|
1711
2491
|
"div",
|
|
1712
2492
|
{
|
|
1713
2493
|
onMouseDown: (e) => e.stopPropagation(),
|
|
@@ -1719,8 +2499,8 @@ var ReactionPicker = ({
|
|
|
1719
2499
|
zIndex: 50,
|
|
1720
2500
|
animation: "hermes-pop 0.15s ease"
|
|
1721
2501
|
},
|
|
1722
|
-
children: /* @__PURE__ */
|
|
1723
|
-
|
|
2502
|
+
children: /* @__PURE__ */ jsx22(
|
|
2503
|
+
EmojiPicker,
|
|
1724
2504
|
{
|
|
1725
2505
|
theme: Theme.DARK,
|
|
1726
2506
|
onEmojiClick: handleEmojiClick,
|
|
@@ -1732,7 +2512,7 @@ var ReactionPicker = ({
|
|
|
1732
2512
|
)
|
|
1733
2513
|
}
|
|
1734
2514
|
),
|
|
1735
|
-
/* @__PURE__ */
|
|
2515
|
+
/* @__PURE__ */ jsx22("style", { children: `
|
|
1736
2516
|
@keyframes hermes-pop {
|
|
1737
2517
|
from {
|
|
1738
2518
|
opacity: 0;
|
|
@@ -1750,7 +2530,7 @@ var ReactionPicker = ({
|
|
|
1750
2530
|
};
|
|
1751
2531
|
|
|
1752
2532
|
// src/react/components/MediaMessage.tsx
|
|
1753
|
-
import { jsx as
|
|
2533
|
+
import { jsx as jsx23, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
1754
2534
|
var formatFileSize2 = (bytes) => {
|
|
1755
2535
|
if (!bytes) return "";
|
|
1756
2536
|
if (bytes >= 1024 * 1024) return `${(bytes / 1024 / 1024).toFixed(1)} MB`;
|
|
@@ -1763,13 +2543,13 @@ var MediaMessage = ({
|
|
|
1763
2543
|
maxWidth = 300
|
|
1764
2544
|
}) => {
|
|
1765
2545
|
if (!message.url) return null;
|
|
1766
|
-
return /* @__PURE__ */
|
|
2546
|
+
return /* @__PURE__ */ jsxs12(
|
|
1767
2547
|
"div",
|
|
1768
2548
|
{
|
|
1769
2549
|
className: `hermes-media-message hermes-media-message--${message.type} ${className}`,
|
|
1770
2550
|
style: { maxWidth },
|
|
1771
2551
|
children: [
|
|
1772
|
-
message.type === "image" && /* @__PURE__ */
|
|
2552
|
+
message.type === "image" && /* @__PURE__ */ jsx23(
|
|
1773
2553
|
"img",
|
|
1774
2554
|
{
|
|
1775
2555
|
src: message.url,
|
|
@@ -1783,7 +2563,7 @@ var MediaMessage = ({
|
|
|
1783
2563
|
onClick: () => window.open(message.url, "_blank")
|
|
1784
2564
|
}
|
|
1785
2565
|
),
|
|
1786
|
-
message.type === "video" && /* @__PURE__ */
|
|
2566
|
+
message.type === "video" && /* @__PURE__ */ jsx23(
|
|
1787
2567
|
"video",
|
|
1788
2568
|
{
|
|
1789
2569
|
src: message.url,
|
|
@@ -1792,17 +2572,17 @@ var MediaMessage = ({
|
|
|
1792
2572
|
style: { width: "100%", borderRadius: 10 }
|
|
1793
2573
|
}
|
|
1794
2574
|
),
|
|
1795
|
-
message.type === "audio" && /* @__PURE__ */
|
|
2575
|
+
message.type === "audio" && /* @__PURE__ */ jsxs12(
|
|
1796
2576
|
"div",
|
|
1797
2577
|
{
|
|
1798
2578
|
style: { display: "flex", alignItems: "center", gap: 8, padding: 8 },
|
|
1799
2579
|
children: [
|
|
1800
|
-
/* @__PURE__ */
|
|
1801
|
-
/* @__PURE__ */
|
|
2580
|
+
/* @__PURE__ */ jsx23("span", { style: { fontSize: 20 }, children: "\u{1F3B5}" }),
|
|
2581
|
+
/* @__PURE__ */ jsx23("audio", { src: message.url, controls: true, style: { flex: 1, height: 36 } })
|
|
1802
2582
|
]
|
|
1803
2583
|
}
|
|
1804
2584
|
),
|
|
1805
|
-
message.type === "document" && /* @__PURE__ */
|
|
2585
|
+
message.type === "document" && /* @__PURE__ */ jsxs12(
|
|
1806
2586
|
"a",
|
|
1807
2587
|
{
|
|
1808
2588
|
href: message.url,
|
|
@@ -1819,9 +2599,9 @@ var MediaMessage = ({
|
|
|
1819
2599
|
color: "inherit"
|
|
1820
2600
|
},
|
|
1821
2601
|
children: [
|
|
1822
|
-
/* @__PURE__ */
|
|
1823
|
-
/* @__PURE__ */
|
|
1824
|
-
/* @__PURE__ */
|
|
2602
|
+
/* @__PURE__ */ jsx23("span", { style: { fontSize: 28, flexShrink: 0 }, children: "\u{1F4C4}" }),
|
|
2603
|
+
/* @__PURE__ */ jsxs12("div", { style: { overflow: "hidden" }, children: [
|
|
2604
|
+
/* @__PURE__ */ jsx23(
|
|
1825
2605
|
"div",
|
|
1826
2606
|
{
|
|
1827
2607
|
style: {
|
|
@@ -1834,7 +2614,7 @@ var MediaMessage = ({
|
|
|
1834
2614
|
children: message.fileName ?? "Document"
|
|
1835
2615
|
}
|
|
1836
2616
|
),
|
|
1837
|
-
/* @__PURE__ */
|
|
2617
|
+
/* @__PURE__ */ jsxs12("div", { style: { fontSize: 11, opacity: 0.6 }, children: [
|
|
1838
2618
|
formatFileSize2(message.fileSize),
|
|
1839
2619
|
" \xB7 Click to download"
|
|
1840
2620
|
] })
|
|
@@ -1842,7 +2622,7 @@ var MediaMessage = ({
|
|
|
1842
2622
|
]
|
|
1843
2623
|
}
|
|
1844
2624
|
),
|
|
1845
|
-
message.type === "link" && /* @__PURE__ */
|
|
2625
|
+
message.type === "link" && /* @__PURE__ */ jsxs12(
|
|
1846
2626
|
"a",
|
|
1847
2627
|
{
|
|
1848
2628
|
href: message.url,
|
|
@@ -1870,21 +2650,435 @@ var MediaMessage = ({
|
|
|
1870
2650
|
}
|
|
1871
2651
|
);
|
|
1872
2652
|
};
|
|
2653
|
+
|
|
2654
|
+
// src/react/components/Thread/ThreadHeader.tsx
|
|
2655
|
+
import { jsx as jsx24, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
2656
|
+
var ThreadHeader = ({
|
|
2657
|
+
thread,
|
|
2658
|
+
onClose,
|
|
2659
|
+
className = ""
|
|
2660
|
+
}) => /* @__PURE__ */ jsxs13(
|
|
2661
|
+
"div",
|
|
2662
|
+
{
|
|
2663
|
+
className: `hermes-thread-header ${className}`,
|
|
2664
|
+
style: {
|
|
2665
|
+
display: "flex",
|
|
2666
|
+
alignItems: "center",
|
|
2667
|
+
justifyContent: "space-between",
|
|
2668
|
+
padding: "12px 16px",
|
|
2669
|
+
borderBottom: "1px solid rgba(128,128,128,0.15)"
|
|
2670
|
+
},
|
|
2671
|
+
children: [
|
|
2672
|
+
/* @__PURE__ */ jsxs13("div", { style: { flex: 1, overflow: "hidden" }, children: [
|
|
2673
|
+
/* @__PURE__ */ jsx24("div", { style: { fontWeight: 700, fontSize: 15, marginBottom: 2 }, children: "Thread" }),
|
|
2674
|
+
/* @__PURE__ */ jsx24(
|
|
2675
|
+
"div",
|
|
2676
|
+
{
|
|
2677
|
+
style: {
|
|
2678
|
+
fontSize: 12,
|
|
2679
|
+
opacity: 0.6,
|
|
2680
|
+
overflow: "hidden",
|
|
2681
|
+
textOverflow: "ellipsis",
|
|
2682
|
+
whiteSpace: "nowrap"
|
|
2683
|
+
},
|
|
2684
|
+
children: thread.type === "text" ? thread.text?.slice(0, 80) : `[${thread.type}]`
|
|
2685
|
+
}
|
|
2686
|
+
)
|
|
2687
|
+
] }),
|
|
2688
|
+
/* @__PURE__ */ jsx24(
|
|
2689
|
+
"button",
|
|
2690
|
+
{
|
|
2691
|
+
onClick: onClose,
|
|
2692
|
+
style: {
|
|
2693
|
+
background: "none",
|
|
2694
|
+
border: "none",
|
|
2695
|
+
cursor: "pointer",
|
|
2696
|
+
fontSize: 18,
|
|
2697
|
+
padding: 4,
|
|
2698
|
+
opacity: 0.6,
|
|
2699
|
+
lineHeight: 1
|
|
2700
|
+
},
|
|
2701
|
+
children: "\u2715"
|
|
2702
|
+
}
|
|
2703
|
+
)
|
|
2704
|
+
]
|
|
2705
|
+
}
|
|
2706
|
+
);
|
|
2707
|
+
|
|
2708
|
+
// src/react/components/Thread/Thread.tsx
|
|
2709
|
+
import { jsx as jsx25, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
2710
|
+
var Thread = ({
|
|
2711
|
+
className = "",
|
|
2712
|
+
autoFocus = true
|
|
2713
|
+
}) => {
|
|
2714
|
+
const { currentUser, customClasses } = useChatContext("Thread");
|
|
2715
|
+
const { thread, threadMessages, threadHasMore, threadLoadingMore } = useRoomStateContext("Thread");
|
|
2716
|
+
const { closeThread, addReaction, deleteMessage, editMessage } = useRoomActionContext("Thread");
|
|
2717
|
+
const {
|
|
2718
|
+
ThreadHeader: CustomThreadHeader,
|
|
2719
|
+
Message: CustomMessage
|
|
2720
|
+
} = useComponentContext("Thread");
|
|
2721
|
+
if (!thread) return null;
|
|
2722
|
+
const ThreadHeaderComponent = CustomThreadHeader || ThreadHeader;
|
|
2723
|
+
const MessageComponent = CustomMessage || Message;
|
|
2724
|
+
const threadClass = customClasses?.thread || `hermes-thread ${className}`.trim();
|
|
2725
|
+
return /* @__PURE__ */ jsxs14(
|
|
2726
|
+
"div",
|
|
2727
|
+
{
|
|
2728
|
+
className: threadClass,
|
|
2729
|
+
style: {
|
|
2730
|
+
display: "flex",
|
|
2731
|
+
flexDirection: "column",
|
|
2732
|
+
height: "100%",
|
|
2733
|
+
borderLeft: "1px solid rgba(128,128,128,0.15)",
|
|
2734
|
+
minWidth: 320,
|
|
2735
|
+
maxWidth: 420
|
|
2736
|
+
},
|
|
2737
|
+
children: [
|
|
2738
|
+
/* @__PURE__ */ jsx25(ThreadHeaderComponent, { thread, onClose: closeThread }),
|
|
2739
|
+
/* @__PURE__ */ jsx25(
|
|
2740
|
+
"div",
|
|
2741
|
+
{
|
|
2742
|
+
style: {
|
|
2743
|
+
padding: "12px 16px",
|
|
2744
|
+
borderBottom: "1px solid rgba(128,128,128,0.1)",
|
|
2745
|
+
background: "rgba(128,128,128,0.03)"
|
|
2746
|
+
},
|
|
2747
|
+
children: /* @__PURE__ */ jsx25(
|
|
2748
|
+
MessageComponent,
|
|
2749
|
+
{
|
|
2750
|
+
message: thread,
|
|
2751
|
+
isOwn: thread.senderId === currentUser?.userId,
|
|
2752
|
+
onReact: (id, emoji) => addReaction(id, emoji),
|
|
2753
|
+
showAvatar: true
|
|
2754
|
+
}
|
|
2755
|
+
)
|
|
2756
|
+
}
|
|
2757
|
+
),
|
|
2758
|
+
/* @__PURE__ */ jsx25(
|
|
2759
|
+
"div",
|
|
2760
|
+
{
|
|
2761
|
+
style: {
|
|
2762
|
+
flex: 1,
|
|
2763
|
+
overflowY: "auto",
|
|
2764
|
+
padding: 16,
|
|
2765
|
+
display: "flex",
|
|
2766
|
+
flexDirection: "column"
|
|
2767
|
+
},
|
|
2768
|
+
children: threadMessages.length === 0 ? /* @__PURE__ */ jsx25(EmptyStateIndicator, { listType: "thread" }) : threadMessages.map((msg) => /* @__PURE__ */ jsx25("div", { style: { marginBottom: 8 }, children: /* @__PURE__ */ jsx25(
|
|
2769
|
+
MessageComponent,
|
|
2770
|
+
{
|
|
2771
|
+
message: msg,
|
|
2772
|
+
isOwn: msg.senderId === currentUser?.userId,
|
|
2773
|
+
onEdit: (id, text) => editMessage(id, text),
|
|
2774
|
+
onDelete: (id) => deleteMessage(id),
|
|
2775
|
+
onReact: (id, emoji) => addReaction(id, emoji),
|
|
2776
|
+
showAvatar: true
|
|
2777
|
+
}
|
|
2778
|
+
) }, msg._id))
|
|
2779
|
+
}
|
|
2780
|
+
)
|
|
2781
|
+
]
|
|
2782
|
+
}
|
|
2783
|
+
);
|
|
2784
|
+
};
|
|
2785
|
+
|
|
2786
|
+
// src/react/components/Modal/Modal.tsx
|
|
2787
|
+
import { useEffect as useEffect11, useCallback as useCallback11 } from "react";
|
|
2788
|
+
import { jsx as jsx26, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
2789
|
+
var Modal = ({
|
|
2790
|
+
open,
|
|
2791
|
+
onClose,
|
|
2792
|
+
className = "",
|
|
2793
|
+
children
|
|
2794
|
+
}) => {
|
|
2795
|
+
const handleKeyDown = useCallback11(
|
|
2796
|
+
(e) => {
|
|
2797
|
+
if (e.key === "Escape") onClose();
|
|
2798
|
+
},
|
|
2799
|
+
[onClose]
|
|
2800
|
+
);
|
|
2801
|
+
useEffect11(() => {
|
|
2802
|
+
if (open) {
|
|
2803
|
+
document.addEventListener("keydown", handleKeyDown);
|
|
2804
|
+
document.body.style.overflow = "hidden";
|
|
2805
|
+
}
|
|
2806
|
+
return () => {
|
|
2807
|
+
document.removeEventListener("keydown", handleKeyDown);
|
|
2808
|
+
document.body.style.overflow = "";
|
|
2809
|
+
};
|
|
2810
|
+
}, [open, handleKeyDown]);
|
|
2811
|
+
if (!open) return null;
|
|
2812
|
+
return /* @__PURE__ */ jsxs15(
|
|
2813
|
+
"div",
|
|
2814
|
+
{
|
|
2815
|
+
className: `hermes-modal-overlay ${className}`,
|
|
2816
|
+
onClick: onClose,
|
|
2817
|
+
style: {
|
|
2818
|
+
position: "fixed",
|
|
2819
|
+
inset: 0,
|
|
2820
|
+
zIndex: 9999,
|
|
2821
|
+
display: "flex",
|
|
2822
|
+
alignItems: "center",
|
|
2823
|
+
justifyContent: "center",
|
|
2824
|
+
background: "rgba(0,0,0,0.6)",
|
|
2825
|
+
backdropFilter: "blur(4px)",
|
|
2826
|
+
animation: "hermes-fade-in 0.15s ease"
|
|
2827
|
+
},
|
|
2828
|
+
children: [
|
|
2829
|
+
/* @__PURE__ */ jsxs15(
|
|
2830
|
+
"div",
|
|
2831
|
+
{
|
|
2832
|
+
className: "hermes-modal-content",
|
|
2833
|
+
onClick: (e) => e.stopPropagation(),
|
|
2834
|
+
style: {
|
|
2835
|
+
maxWidth: "90vw",
|
|
2836
|
+
maxHeight: "90vh",
|
|
2837
|
+
overflow: "auto",
|
|
2838
|
+
borderRadius: 12,
|
|
2839
|
+
background: "#fff",
|
|
2840
|
+
boxShadow: "0 16px 64px rgba(0,0,0,0.3)",
|
|
2841
|
+
animation: "hermes-pop 0.2s ease"
|
|
2842
|
+
},
|
|
2843
|
+
children: [
|
|
2844
|
+
/* @__PURE__ */ jsx26(
|
|
2845
|
+
"button",
|
|
2846
|
+
{
|
|
2847
|
+
onClick: onClose,
|
|
2848
|
+
style: {
|
|
2849
|
+
position: "absolute",
|
|
2850
|
+
top: 16,
|
|
2851
|
+
right: 16,
|
|
2852
|
+
background: "rgba(0,0,0,0.5)",
|
|
2853
|
+
color: "#fff",
|
|
2854
|
+
border: "none",
|
|
2855
|
+
borderRadius: "50%",
|
|
2856
|
+
width: 32,
|
|
2857
|
+
height: 32,
|
|
2858
|
+
cursor: "pointer",
|
|
2859
|
+
fontSize: 16,
|
|
2860
|
+
display: "flex",
|
|
2861
|
+
alignItems: "center",
|
|
2862
|
+
justifyContent: "center",
|
|
2863
|
+
zIndex: 1
|
|
2864
|
+
},
|
|
2865
|
+
children: "\u2715"
|
|
2866
|
+
}
|
|
2867
|
+
),
|
|
2868
|
+
children
|
|
2869
|
+
]
|
|
2870
|
+
}
|
|
2871
|
+
),
|
|
2872
|
+
/* @__PURE__ */ jsx26("style", { children: `
|
|
2873
|
+
@keyframes hermes-fade-in {
|
|
2874
|
+
from { opacity: 0; }
|
|
2875
|
+
to { opacity: 1; }
|
|
2876
|
+
}
|
|
2877
|
+
@keyframes hermes-pop {
|
|
2878
|
+
from { opacity: 0; transform: scale(0.9); }
|
|
2879
|
+
to { opacity: 1; transform: scale(1); }
|
|
2880
|
+
}
|
|
2881
|
+
` })
|
|
2882
|
+
]
|
|
2883
|
+
}
|
|
2884
|
+
);
|
|
2885
|
+
};
|
|
2886
|
+
|
|
2887
|
+
// src/react/components/Search/Search.tsx
|
|
2888
|
+
import { useState as useState12, useCallback as useCallback12, useMemo as useMemo3 } from "react";
|
|
2889
|
+
import { jsx as jsx27, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
2890
|
+
var Search = ({
|
|
2891
|
+
messages = [],
|
|
2892
|
+
onSelectResult,
|
|
2893
|
+
placeholder = "Search messages...",
|
|
2894
|
+
className = ""
|
|
2895
|
+
}) => {
|
|
2896
|
+
const [query, setQuery] = useState12("");
|
|
2897
|
+
const [focused, setFocused] = useState12(false);
|
|
2898
|
+
const results = useMemo3(() => {
|
|
2899
|
+
if (!query.trim()) return [];
|
|
2900
|
+
const lower = query.toLowerCase();
|
|
2901
|
+
return messages.filter(
|
|
2902
|
+
(m) => !m.isDeleted && m.type === "text" && m.text?.toLowerCase().includes(lower)
|
|
2903
|
+
).slice(0, 20);
|
|
2904
|
+
}, [query, messages]);
|
|
2905
|
+
const handleSelect = useCallback12(
|
|
2906
|
+
(msg) => {
|
|
2907
|
+
onSelectResult?.(msg);
|
|
2908
|
+
setQuery("");
|
|
2909
|
+
setFocused(false);
|
|
2910
|
+
},
|
|
2911
|
+
[onSelectResult]
|
|
2912
|
+
);
|
|
2913
|
+
return /* @__PURE__ */ jsxs16(
|
|
2914
|
+
"div",
|
|
2915
|
+
{
|
|
2916
|
+
className: `hermes-search ${className}`,
|
|
2917
|
+
style: { position: "relative" },
|
|
2918
|
+
children: [
|
|
2919
|
+
/* @__PURE__ */ jsxs16(
|
|
2920
|
+
"div",
|
|
2921
|
+
{
|
|
2922
|
+
style: {
|
|
2923
|
+
display: "flex",
|
|
2924
|
+
alignItems: "center",
|
|
2925
|
+
gap: 8,
|
|
2926
|
+
padding: "6px 12px",
|
|
2927
|
+
border: "1px solid rgba(128,128,128,0.2)",
|
|
2928
|
+
borderRadius: 10,
|
|
2929
|
+
background: focused ? "#fff" : "rgba(128,128,128,0.05)",
|
|
2930
|
+
transition: "background 0.15s, border-color 0.15s",
|
|
2931
|
+
borderColor: focused ? "#0084ff" : "rgba(128,128,128,0.2)"
|
|
2932
|
+
},
|
|
2933
|
+
children: [
|
|
2934
|
+
/* @__PURE__ */ jsx27("span", { style: { fontSize: 14, opacity: 0.5 }, children: "\u{1F50D}" }),
|
|
2935
|
+
/* @__PURE__ */ jsx27(
|
|
2936
|
+
"input",
|
|
2937
|
+
{
|
|
2938
|
+
type: "text",
|
|
2939
|
+
value: query,
|
|
2940
|
+
onChange: (e) => setQuery(e.target.value),
|
|
2941
|
+
onFocus: () => setFocused(true),
|
|
2942
|
+
onBlur: () => setTimeout(() => setFocused(false), 200),
|
|
2943
|
+
placeholder,
|
|
2944
|
+
style: {
|
|
2945
|
+
flex: 1,
|
|
2946
|
+
border: "none",
|
|
2947
|
+
outline: "none",
|
|
2948
|
+
fontSize: 13,
|
|
2949
|
+
background: "transparent"
|
|
2950
|
+
}
|
|
2951
|
+
}
|
|
2952
|
+
),
|
|
2953
|
+
query && /* @__PURE__ */ jsx27(
|
|
2954
|
+
"button",
|
|
2955
|
+
{
|
|
2956
|
+
onClick: () => setQuery(""),
|
|
2957
|
+
style: {
|
|
2958
|
+
background: "none",
|
|
2959
|
+
border: "none",
|
|
2960
|
+
cursor: "pointer",
|
|
2961
|
+
fontSize: 14,
|
|
2962
|
+
opacity: 0.5,
|
|
2963
|
+
lineHeight: 1
|
|
2964
|
+
},
|
|
2965
|
+
children: "\u2715"
|
|
2966
|
+
}
|
|
2967
|
+
)
|
|
2968
|
+
]
|
|
2969
|
+
}
|
|
2970
|
+
),
|
|
2971
|
+
focused && query.trim() && /* @__PURE__ */ jsx27(
|
|
2972
|
+
"div",
|
|
2973
|
+
{
|
|
2974
|
+
style: {
|
|
2975
|
+
position: "absolute",
|
|
2976
|
+
top: "calc(100% + 4px)",
|
|
2977
|
+
left: 0,
|
|
2978
|
+
right: 0,
|
|
2979
|
+
zIndex: 50,
|
|
2980
|
+
background: "#fff",
|
|
2981
|
+
border: "1px solid rgba(128,128,128,0.15)",
|
|
2982
|
+
borderRadius: 10,
|
|
2983
|
+
boxShadow: "0 8px 32px rgba(0,0,0,0.12)",
|
|
2984
|
+
maxHeight: 300,
|
|
2985
|
+
overflowY: "auto"
|
|
2986
|
+
},
|
|
2987
|
+
children: results.length === 0 ? /* @__PURE__ */ jsx27(
|
|
2988
|
+
"div",
|
|
2989
|
+
{
|
|
2990
|
+
style: {
|
|
2991
|
+
padding: 16,
|
|
2992
|
+
textAlign: "center",
|
|
2993
|
+
fontSize: 13,
|
|
2994
|
+
opacity: 0.5
|
|
2995
|
+
},
|
|
2996
|
+
children: "No results found"
|
|
2997
|
+
}
|
|
2998
|
+
) : results.map((msg) => /* @__PURE__ */ jsxs16(
|
|
2999
|
+
"div",
|
|
3000
|
+
{
|
|
3001
|
+
onClick: () => handleSelect(msg),
|
|
3002
|
+
style: {
|
|
3003
|
+
padding: "8px 12px",
|
|
3004
|
+
cursor: "pointer",
|
|
3005
|
+
borderBottom: "1px solid rgba(128,128,128,0.08)",
|
|
3006
|
+
transition: "background 0.1s"
|
|
3007
|
+
},
|
|
3008
|
+
onMouseEnter: (e) => e.currentTarget.style.background = "rgba(0,132,255,0.05)",
|
|
3009
|
+
onMouseLeave: (e) => e.currentTarget.style.background = "transparent",
|
|
3010
|
+
children: [
|
|
3011
|
+
/* @__PURE__ */ jsx27(
|
|
3012
|
+
"div",
|
|
3013
|
+
{
|
|
3014
|
+
style: {
|
|
3015
|
+
fontSize: 13,
|
|
3016
|
+
overflow: "hidden",
|
|
3017
|
+
textOverflow: "ellipsis",
|
|
3018
|
+
whiteSpace: "nowrap"
|
|
3019
|
+
},
|
|
3020
|
+
children: msg.text
|
|
3021
|
+
}
|
|
3022
|
+
),
|
|
3023
|
+
/* @__PURE__ */ jsx27("div", { style: { fontSize: 11, opacity: 0.5, marginTop: 2 }, children: new Date(msg.createdAt).toLocaleString() })
|
|
3024
|
+
]
|
|
3025
|
+
},
|
|
3026
|
+
msg._id
|
|
3027
|
+
))
|
|
3028
|
+
}
|
|
3029
|
+
)
|
|
3030
|
+
]
|
|
3031
|
+
}
|
|
3032
|
+
);
|
|
3033
|
+
};
|
|
1873
3034
|
export {
|
|
3035
|
+
Avatar,
|
|
3036
|
+
Chat,
|
|
3037
|
+
ChatContext,
|
|
1874
3038
|
ChatInput,
|
|
3039
|
+
ChatProvider,
|
|
3040
|
+
ComponentContext,
|
|
3041
|
+
ComponentProvider,
|
|
3042
|
+
DateSeparator,
|
|
3043
|
+
EmptyStateIndicator,
|
|
1875
3044
|
HermesClient,
|
|
3045
|
+
LoadingErrorIndicator,
|
|
3046
|
+
LoadingIndicator,
|
|
1876
3047
|
MediaMessage,
|
|
3048
|
+
Message,
|
|
3049
|
+
MessageActions,
|
|
3050
|
+
MessageContext,
|
|
1877
3051
|
MessageList,
|
|
3052
|
+
MessageProvider,
|
|
3053
|
+
MessageStatus,
|
|
3054
|
+
Modal,
|
|
1878
3055
|
OnlineBadge,
|
|
1879
3056
|
ReactionPicker,
|
|
3057
|
+
Room,
|
|
3058
|
+
RoomActionContext,
|
|
3059
|
+
RoomActionProvider,
|
|
1880
3060
|
RoomList,
|
|
1881
|
-
|
|
3061
|
+
RoomStateContext,
|
|
3062
|
+
RoomStateProvider,
|
|
3063
|
+
Search,
|
|
3064
|
+
Thread,
|
|
3065
|
+
ThreadHeader,
|
|
3066
|
+
TypingContext,
|
|
3067
|
+
TypingIndicator,
|
|
3068
|
+
TypingProvider,
|
|
3069
|
+
Window,
|
|
3070
|
+
useChatContext,
|
|
3071
|
+
useComponentContext,
|
|
3072
|
+
useMessageContext,
|
|
1882
3073
|
useMessages,
|
|
1883
3074
|
usePresence,
|
|
1884
3075
|
useReactions,
|
|
1885
3076
|
useReadReceipts,
|
|
3077
|
+
useRoomActionContext,
|
|
3078
|
+
useRoomStateContext,
|
|
1886
3079
|
useRooms,
|
|
1887
3080
|
useTyping,
|
|
3081
|
+
useTypingContext,
|
|
1888
3082
|
useUpload
|
|
1889
3083
|
};
|
|
1890
3084
|
//# sourceMappingURL=react.js.map
|