@ermis-network/ermis-chat-react 1.0.9 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +144 -0
- package/dist/index.cjs +8320 -3427
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +1277 -291
- package/dist/index.css.map +1 -1
- package/dist/index.d.mts +1131 -99
- package/dist/index.d.ts +1131 -99
- package/dist/index.mjs +8168 -3319
- package/dist/index.mjs.map +1 -1
- package/package.json +9 -4
- package/src/channelTypeUtils.ts +1 -1
- package/src/components/Avatar.tsx +2 -1
- package/src/components/Channel.tsx +6 -5
- package/src/components/ChannelActions.tsx +67 -3
- package/src/components/ChannelHeader.tsx +27 -37
- package/src/components/ChannelInfo/AddMemberModal.tsx +12 -2
- package/src/components/ChannelInfo/ChannelInfo.tsx +410 -187
- package/src/components/ChannelInfo/ChannelInfoTabs.tsx +59 -297
- package/src/components/ChannelInfo/ChannelSettingsPanel.tsx +30 -174
- package/src/components/ChannelInfo/EditChannelModal.tsx +6 -3
- package/src/components/ChannelInfo/MediaGridItem.tsx +215 -68
- package/src/components/ChannelInfo/MemberListItem.tsx +2 -3
- package/src/components/ChannelInfo/MessageSearchPanel.tsx +27 -126
- package/src/components/ChannelInfo/States.tsx +1 -1
- package/src/components/ChannelInfo/index.ts +3 -0
- package/src/components/ChannelInfo/useChannelInfoTabs.tsx +427 -0
- package/src/components/ChannelInfo/useChannelSettings.ts +212 -0
- package/src/components/ChannelInfo/useMessageSearch.tsx +141 -0
- package/src/components/ChannelList.tsx +247 -301
- package/src/components/CreateChannelModal.tsx +290 -93
- package/src/components/Dropdown.tsx +1 -16
- package/src/components/EditPreview.tsx +1 -0
- package/src/components/ErmisCallProvider.tsx +72 -17
- package/src/components/ErmisCallUI.tsx +43 -20
- package/src/components/FilesPreview.tsx +8 -12
- package/src/components/FlatTopicGroupItem.tsx +243 -0
- package/src/components/ForwardMessageModal.tsx +43 -81
- package/src/components/MediaLightbox.tsx +454 -292
- package/src/components/MentionSuggestions.tsx +47 -35
- package/src/components/MessageActionsBox.tsx +6 -1
- package/src/components/MessageInput.tsx +165 -17
- package/src/components/MessageInputDefaults.tsx +127 -1
- package/src/components/MessageItem.tsx +155 -43
- package/src/components/MessageQuickReactions.tsx +153 -23
- package/src/components/MessageReactions.tsx +49 -3
- package/src/components/MessageRenderers.tsx +1114 -445
- package/src/components/Panel.tsx +1 -14
- package/src/components/PinnedMessages.tsx +55 -15
- package/src/components/PreviewOverlay.tsx +24 -0
- package/src/components/QuotedMessagePreview.tsx +99 -8
- package/src/components/ReadReceipts.tsx +2 -1
- package/src/components/RecoveryPin/RecoveryPin.tsx +279 -0
- package/src/components/RecoveryPin/index.ts +19 -0
- package/src/components/TopicList.tsx +236 -0
- package/src/components/TopicModal.tsx +4 -1
- package/src/components/TypingIndicator.tsx +17 -8
- package/src/components/UserPicker.tsx +94 -16
- package/src/components/VirtualMessageList.tsx +419 -113
- package/src/context/ChatComponentsContext.tsx +14 -0
- package/src/context/ChatProvider.tsx +44 -14
- package/src/context/ErmisCallContext.tsx +4 -0
- package/src/hooks/useChannelCapabilities.ts +7 -4
- package/src/hooks/useChannelData.ts +10 -3
- package/src/hooks/useChannelListUpdates.ts +94 -21
- package/src/hooks/useChannelMessages.ts +391 -42
- package/src/hooks/useChannelRowUpdates.ts +36 -5
- package/src/hooks/useChatUser.ts +39 -0
- package/src/hooks/useContactChannels.ts +45 -0
- package/src/hooks/useContactCount.ts +50 -0
- package/src/hooks/useDownloadHandler.ts +36 -0
- package/src/hooks/useDragAndDrop.ts +79 -0
- package/src/hooks/useE2eeAttachmentRenderer.ts +204 -0
- package/src/hooks/useE2eeFileUpload.ts +38 -0
- package/src/hooks/useFileUpload.ts +25 -5
- package/src/hooks/useForwardMessage.ts +309 -0
- package/src/hooks/useInviteChannels.ts +88 -0
- package/src/hooks/useInviteCount.ts +104 -0
- package/src/hooks/useLoadMessages.ts +16 -4
- package/src/hooks/useMentions.ts +60 -7
- package/src/hooks/useMessageActions.ts +19 -10
- package/src/hooks/useMessageSend.ts +64 -12
- package/src/hooks/usePendingE2eeSends.ts +29 -0
- package/src/hooks/usePendingState.ts +21 -4
- package/src/hooks/usePreviewState.ts +69 -0
- package/src/hooks/useRecoveryPin.ts +287 -0
- package/src/hooks/useScrollToMessage.ts +29 -4
- package/src/hooks/useStickerPicker.ts +62 -0
- package/src/hooks/useTopicGroupUpdates.ts +235 -0
- package/src/index.ts +79 -6
- package/src/messageTypeUtils.ts +27 -1
- package/src/styles/_base.css +0 -1
- package/src/styles/_call-ui.css +59 -2
- package/src/styles/_channel-info.css +50 -4
- package/src/styles/_channel-list.css +131 -68
- package/src/styles/_create-channel-modal.css +10 -0
- package/src/styles/_forward-modal.css +16 -1
- package/src/styles/_media-lightbox.css +67 -2
- package/src/styles/_mentions.css +1 -1
- package/src/styles/_message-actions.css +3 -4
- package/src/styles/_message-bubble.css +631 -112
- package/src/styles/_message-input.css +139 -0
- package/src/styles/_message-list.css +91 -18
- package/src/styles/_message-quick-reactions.css +105 -32
- package/src/styles/_message-reactions.css +22 -32
- package/src/styles/_modal.css +2 -1
- package/src/styles/_preview-overlay.css +38 -0
- package/src/styles/_recovery-pin.css +97 -0
- package/src/styles/_tokens.css +22 -20
- package/src/styles/_typing-indicator.css +26 -10
- package/src/styles/index.css +2 -0
- package/src/types.ts +477 -15
- package/src/utils/avatarColors.ts +48 -0
- package/src/utils.ts +219 -16
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import React, { useState, useEffect, useCallback, useMemo, useRef } from 'react';
|
|
2
|
-
import { createForwardMessagePayload } from '@ermis-network/ermis-chat-sdk';
|
|
3
|
-
import type { Channel } from '@ermis-network/ermis-chat-sdk';
|
|
4
2
|
import { useChatClient } from '../hooks/useChatClient';
|
|
5
3
|
import { Avatar } from './Avatar';
|
|
6
|
-
import { Modal } from './Modal';
|
|
7
|
-
import
|
|
4
|
+
import { Modal as DefaultModal } from './Modal';
|
|
5
|
+
import { useChatComponents } from '../context/ChatComponentsContext';
|
|
6
|
+
import type { ForwardMessageModalProps, ForwardChannelItemProps } from '../types';
|
|
8
7
|
import { isTopicChannel } from '../channelTypeUtils';
|
|
8
|
+
import { useForwardMessage } from '../hooks/useForwardMessage';
|
|
9
9
|
|
|
10
10
|
export type { ForwardMessageModalProps, ForwardChannelItemProps } from '../types';
|
|
11
11
|
|
|
@@ -18,12 +18,20 @@ const DefaultForwardChannelItem: React.FC<ForwardChannelItemProps> = React.memo(
|
|
|
18
18
|
onToggle,
|
|
19
19
|
AvatarComponent,
|
|
20
20
|
}) => {
|
|
21
|
+
const { client } = useChatClient();
|
|
22
|
+
const isTopic = isTopicChannel(channel);
|
|
23
|
+
const parentCid = channel.data?.parent_cid as string | undefined;
|
|
24
|
+
const parent = parentCid ? client.activeChannels[parentCid] : null;
|
|
25
|
+
const parentName = parent?.data?.name || '';
|
|
26
|
+
|
|
21
27
|
const name = (channel.data?.name || channel.cid) as string;
|
|
22
28
|
const rawImage = channel.data?.image as string | undefined;
|
|
23
29
|
// Parse emoji:// format → extract just the emoji for avatar fallback
|
|
24
30
|
const isEmoji = rawImage?.startsWith('emoji://');
|
|
25
31
|
const image = isEmoji ? undefined : rawImage;
|
|
26
|
-
|
|
32
|
+
|
|
33
|
+
// Use # for topics without explicit emoji/image
|
|
34
|
+
const emojiIcon = isEmoji ? rawImage!.replace('emoji://', '') : (isTopic && !image ? '#' : undefined);
|
|
27
35
|
|
|
28
36
|
return (
|
|
29
37
|
<div
|
|
@@ -35,7 +43,12 @@ const DefaultForwardChannelItem: React.FC<ForwardChannelItemProps> = React.memo(
|
|
|
35
43
|
) : (
|
|
36
44
|
<AvatarComponent image={image} name={name} size={36} />
|
|
37
45
|
)}
|
|
38
|
-
<
|
|
46
|
+
<div className="ermis-forward-modal__channel-name-container">
|
|
47
|
+
{isTopic && parentName && (
|
|
48
|
+
<span className="ermis-forward-modal__channel-parent-name">{parentName}</span>
|
|
49
|
+
)}
|
|
50
|
+
<span className="ermis-forward-modal__channel-name">{name}</span>
|
|
51
|
+
</div>
|
|
39
52
|
<div className={`ermis-forward-modal__checkbox ${selected ? 'ermis-forward-modal__checkbox--checked' : ''}`}>
|
|
40
53
|
{selected && (
|
|
41
54
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round">
|
|
@@ -57,79 +70,21 @@ export const ForwardMessageModal: React.FC<ForwardMessageModalProps> = ({
|
|
|
57
70
|
ChannelItemComponent = DefaultForwardChannelItem,
|
|
58
71
|
SearchInputComponent,
|
|
59
72
|
}) => {
|
|
60
|
-
const {
|
|
61
|
-
const
|
|
62
|
-
const [search, setSearch] = useState('');
|
|
63
|
-
const [sending, setSending] = useState(false);
|
|
64
|
-
const [results, setResults] = useState<{ success: string[]; failed: string[] } | null>(null);
|
|
73
|
+
const { ModalComponent } = useChatComponents();
|
|
74
|
+
const Modal = ModalComponent || DefaultModal;
|
|
65
75
|
const backdropRef = useRef<HTMLDivElement>(null);
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
return channels.filter((ch) => {
|
|
79
|
-
const name = ((ch.data?.name || ch.cid) as string).toLowerCase();
|
|
80
|
-
return name.includes(q);
|
|
81
|
-
});
|
|
82
|
-
}, [channels, search]);
|
|
83
|
-
|
|
84
|
-
/* ---------- Toggle selection ---------- */
|
|
85
|
-
const toggleChannel = useCallback((channel: Channel) => {
|
|
86
|
-
setSelectedChannels((prev) => {
|
|
87
|
-
const next = new Set(prev);
|
|
88
|
-
if (next.has(channel.cid)) {
|
|
89
|
-
next.delete(channel.cid);
|
|
90
|
-
} else {
|
|
91
|
-
next.add(channel.cid);
|
|
92
|
-
}
|
|
93
|
-
return next;
|
|
94
|
-
});
|
|
95
|
-
}, []);
|
|
96
|
-
|
|
97
|
-
/* ---------- Send forward ---------- */
|
|
98
|
-
const handleSend = useCallback(async () => {
|
|
99
|
-
if (!activeChannel || selectedChannels.size === 0 || sending) return;
|
|
100
|
-
setSending(true);
|
|
101
|
-
const success: string[] = [];
|
|
102
|
-
const failed: string[] = [];
|
|
103
|
-
|
|
104
|
-
for (const cid of selectedChannels) {
|
|
105
|
-
const targetChannel = channels.find((c) => c.cid === cid);
|
|
106
|
-
if (!targetChannel) continue;
|
|
107
|
-
try {
|
|
108
|
-
const forwardPayload = createForwardMessagePayload(
|
|
109
|
-
message,
|
|
110
|
-
targetChannel.cid as string,
|
|
111
|
-
activeChannel.cid as string,
|
|
112
|
-
);
|
|
113
|
-
|
|
114
|
-
await activeChannel.forwardMessage(forwardPayload, {
|
|
115
|
-
type: targetChannel.type,
|
|
116
|
-
channelID: targetChannel.id!,
|
|
117
|
-
});
|
|
118
|
-
success.push((targetChannel.data?.name || targetChannel.cid) as string);
|
|
119
|
-
} catch (err) {
|
|
120
|
-
console.error(`Failed to forward to ${cid}`, err);
|
|
121
|
-
failed.push((targetChannel.data?.name || targetChannel.cid) as string);
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
setResults({ success, failed });
|
|
126
|
-
setSending(false);
|
|
127
|
-
|
|
128
|
-
// Auto-close after success (short delay)
|
|
129
|
-
if (failed.length === 0) {
|
|
130
|
-
setTimeout(() => onDismiss(), 1200);
|
|
131
|
-
}
|
|
132
|
-
}, [activeChannel, selectedChannels, channels, message, sending, onDismiss]);
|
|
76
|
+
const { client } = useChatClient();
|
|
77
|
+
|
|
78
|
+
const {
|
|
79
|
+
search,
|
|
80
|
+
setSearch,
|
|
81
|
+
selectedChannels,
|
|
82
|
+
toggleChannel,
|
|
83
|
+
sending,
|
|
84
|
+
results,
|
|
85
|
+
filteredChannels,
|
|
86
|
+
handleSend,
|
|
87
|
+
} = useForwardMessage(message, onDismiss);
|
|
133
88
|
|
|
134
89
|
/* ---------- Keyboard / backdrop close ---------- */
|
|
135
90
|
useEffect(() => {
|
|
@@ -145,9 +100,16 @@ export const ForwardMessageModal: React.FC<ForwardMessageModalProps> = ({
|
|
|
145
100
|
}, [onDismiss]);
|
|
146
101
|
|
|
147
102
|
/* ---------- Message preview ---------- */
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
103
|
+
let previewText = message.text || '';
|
|
104
|
+
|
|
105
|
+
if (previewText && message.mentioned_users && message.mentioned_users.length > 0) {
|
|
106
|
+
message.mentioned_users.forEach((userId) => {
|
|
107
|
+
const name = client.state.users[userId]?.name || userId;
|
|
108
|
+
previewText = previewText.replace(new RegExp(`@${userId}`, 'g'), `@${name}`);
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
previewText = previewText.length > 120 ? previewText.slice(0, 120) + '…' : previewText;
|
|
151
113
|
const attachmentCount = message.attachments?.length ?? 0;
|
|
152
114
|
|
|
153
115
|
const footer = (
|