@ethora/chat-component 25.12.1 → 26.1.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 +587 -145
- package/dist/components/MainComponents/MessageContainer.d.ts +1 -0
- package/dist/components/MessageBubble/MessageReply.d.ts +2 -2
- package/dist/components/MessageNotification/MessageNotificationToast.d.ts +17 -0
- package/dist/components/MessageNotification/index.d.ts +2 -0
- package/dist/components/Modals/SettingsModals/SharedStyledComponents.d.ts +22 -0
- package/dist/components/Modals/styledModalComponents.d.ts +28 -0
- package/dist/components/styled/Button.d.ts +2 -2
- package/dist/components/styled/DateLabel.d.ts +2 -2
- package/dist/components/styled/StyledComponents.d.ts +10 -10
- package/dist/components/styled/StyledInputComponents/StyledInputComponents.d.ts +6 -6
- package/dist/context/MessageNotificationContext.d.ts +12 -0
- package/dist/firebase-config.d.ts +6 -2
- package/dist/firebase-messaging-sw.js +351 -0
- package/dist/helpers/getDataFromXml.d.ts +1 -0
- package/dist/helpers/initRoomsPresence.d.ts +1 -1
- package/dist/helpers/storeConsole.d.ts +6 -0
- package/dist/hooks/useInAppNotifications.d.ts +18 -0
- package/dist/hooks/usePushNotifications.d.ts +45 -0
- package/dist/hooks/useTabVisibility.d.ts +1 -0
- package/dist/main.css +1 -1
- package/dist/main.d.ts +5 -0
- package/dist/main.js +14698 -11894
- package/dist/main.js.map +1 -1
- package/dist/networking/api-requests/push.api.d.ts +18 -0
- package/dist/networking/stanzaHandlers.d.ts +4 -2
- package/dist/networking/xmpp/allRoomPresences.xmpp.d.ts +11 -1
- package/dist/networking/xmpp/presenceInRoom.xmpp.d.ts +1 -1
- package/dist/networking/xmpp/sendTextMessage.xmpp.d.ts +1 -1
- package/dist/networking/xmpp/sendTextMessageWithTranslateTag.xmpp.d.ts +1 -1
- package/dist/networking/xmpp/subscribeToRoomMessages.xmpp.d.ts +9 -0
- package/dist/networking/xmppClient.d.ts +13 -3
- package/dist/roomStore/chatSettingsSlice.d.ts +1 -0
- package/dist/roomStore/index.d.ts +28 -0
- package/dist/roomStore/roomHeapSlice.d.ts +1 -1
- package/dist/roomStore/roomsSlice.d.ts +11 -1
- package/dist/types/models/config.model.d.ts +36 -1
- package/dist/types/models/room.model.d.ts +4 -1
- package/dist/types/models/xmpp.model.d.ts +3 -1
- package/dist/utils/firebasePushNotifications.d.ts +34 -0
- package/dist/utils/formatError.d.ts +1 -0
- package/dist/utils/messageNotificationManager.d.ts +16 -0
- package/dist/utils/notificationPolicy.d.ts +45 -0
- package/dist/utils/notificationUtils.d.ts +22 -0
- package/dist/utils/pushSubscriptionService.d.ts +12 -0
- package/dist/version.d.ts +1 -1
- package/package.json +7 -4
- package/public/firebase-messaging-sw.js +351 -0
- package/scripts/init-push.js +48 -0
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Ethora Chat Component
|
|
1
|
+
# Ethora Chat Component (`@ethora/chat-component`)
|
|
2
2
|
|
|
3
3
|
      <a href="https://codeclimate.com/github/dappros/ethora-chat-component/maintainability"><img src="https://api.codeclimate.com/v1/badges/715c6f3ffb08de5ca621/maintainability" /></a>     
|
|
4
4
|
|
|
@@ -7,221 +7,663 @@
|
|
|
7
7
|
|
|
8
8
|
[](https://discord.gg/Sm6bAHA3ZC) [](https://twitter.com/intent/tweet?url=https%3A%2F%2Fgithub.com%2Fdappros%2Fethora%2F&via=tarasfilatov&text=check%20out%20Ethora%20%23web3%20%23social%20app%20engine&hashtags=lowcode%2Creactnative%2Copensource%2Cnocode) [](https://ethora.com/) [](https://www.youtube.com/channel/UCRvrXwMOU0WBkRZyFlU7V_g)
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
React + TypeScript chat UI component powered by Ethora backend APIs and XMPP.
|
|
11
|
+
Use it as a standalone chat page, as an embedded widget in your existing app, or as a customizable chat foundation with your own auth and UI.
|
|
12
|
+
|
|
13
|
+
## Table of Contents
|
|
14
|
+
|
|
15
|
+
- [Overview](#overview)
|
|
16
|
+
- [Why Ethora](#why-ethora)
|
|
17
|
+
- [Quick Start](#quick-start)
|
|
18
|
+
- [Integration Modes](#integration-modes)
|
|
19
|
+
- [Behavior Notes and Legacy Quirks](#behavior-notes-and-legacy-quirks)
|
|
20
|
+
- [Chat Props Reference](#chat-props-reference)
|
|
21
|
+
- [Full Config Reference (`IConfig`)](#full-config-reference-iconfig)
|
|
22
|
+
- [Custom Widgets and Overrides](#custom-widgets-and-overrides)
|
|
23
|
+
- [Push Notifications](#push-notifications)
|
|
24
|
+
- [Auth Strategies](#auth-strategies)
|
|
25
|
+
- [Hooks and API Exports](#hooks-and-api-exports)
|
|
26
|
+
- [Use Cases and Feature Coverage](#use-cases-and-feature-coverage)
|
|
27
|
+
- [Hosted vs Self-Host Guidance](#hosted-vs-self-host-guidance)
|
|
28
|
+
- [Security Notes](#security-notes)
|
|
29
|
+
- [Reference Architectures](#reference-architectures)
|
|
30
|
+
- [Use-Case Templates](#use-case-templates)
|
|
31
|
+
- [Feature Roadmap Snapshot](#feature-roadmap-snapshot)
|
|
32
|
+
- [Troubleshooting](#troubleshooting)
|
|
33
|
+
- [Ethora Links and Support](#ethora-links-and-support)
|
|
34
|
+
|
|
35
|
+
## Overview
|
|
36
|
+
|
|
37
|
+
`@ethora/chat-component` gives you a production-oriented chat interface with:
|
|
38
|
+
|
|
39
|
+
- Room list and room chat UI
|
|
40
|
+
- Message history, replies, reactions, edits, deletes
|
|
41
|
+
- Typing indicators
|
|
42
|
+
- In-app notifications + Web Push integration
|
|
43
|
+
- Configurable auth modes (default/login form/google/jwt/custom user)
|
|
44
|
+
- Custom render components for message/input/scroll/day separator/new-message label
|
|
45
|
+
|
|
46
|
+
The package exports:
|
|
47
|
+
|
|
48
|
+
- `Chat` (main component)
|
|
49
|
+
- `XmppProvider`
|
|
50
|
+
- `useUnread`
|
|
51
|
+
- `logoutService`
|
|
52
|
+
- `useQRCodeChat`, `handleQRChatId`
|
|
53
|
+
- `useInAppNotifications`
|
|
54
|
+
- `usePushNotifications`
|
|
55
|
+
- `resendMessage`
|
|
56
|
+
|
|
57
|
+
## Why Ethora
|
|
58
|
+
|
|
59
|
+
Ethora provides hosted and customizable messaging infrastructure plus a wider product ecosystem.
|
|
60
|
+
|
|
61
|
+
| Dimension | Ethora Chat Component | Full Ethora Platform |
|
|
62
|
+
| --- | --- | --- |
|
|
63
|
+
| Primary goal | Embed chat quickly in a React app | End-to-end product stack (chat, profiles, wallets, AI, admin) |
|
|
64
|
+
| Time to first chat | Minutes | Higher initial setup, broader capabilities |
|
|
65
|
+
| Frontend scope | Focused web chat UI package | Multi-product ecosystem and broader SDK/tooling |
|
|
66
|
+
| Custom UI control | High via props + custom components | High, with additional platform-specific tooling |
|
|
67
|
+
| Best fit | Support chat, portal messaging, embedded chat widget | Full social/messaging app platforms with extended modules |
|
|
68
|
+
|
|
69
|
+
## Quick Start
|
|
70
|
+
|
|
71
|
+
### 1. Install
|
|
72
|
+
|
|
73
|
+
| Tool | Command |
|
|
74
|
+
| --- | --- |
|
|
75
|
+
| npm | `npm i @ethora/chat-component` |
|
|
76
|
+
| yarn | `yarn add @ethora/chat-component` |
|
|
77
|
+
| pnpm | `pnpm add @ethora/chat-component` |
|
|
78
|
+
| bun | `bun add @ethora/chat-component` |
|
|
79
|
+
|
|
80
|
+
### 2. Render the chat
|
|
81
|
+
|
|
82
|
+
```tsx
|
|
83
|
+
import { Chat, XmppProvider } from '@ethora/chat-component';
|
|
84
|
+
import './App.css';
|
|
85
|
+
|
|
86
|
+
export default function App() {
|
|
87
|
+
return (
|
|
88
|
+
<XmppProvider>
|
|
89
|
+
<Chat />
|
|
90
|
+
</XmppProvider>
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
```
|
|
11
94
|
|
|
12
|
-
|
|
13
|
-
Sounds simple and is easy to build your app with.
|
|
14
|
-
Uses XMPP chat protocol and ejabberd chat server to provide your users with a seamless instant messaging experience.
|
|
95
|
+
### Required wrapper (`XmppProvider`)
|
|
15
96
|
|
|
16
|
-
|
|
97
|
+
`Chat` relies on internals that use `useXmppClient()`. In real integrations, wrap `Chat` (or your entire app shell) with `XmppProvider`:
|
|
17
98
|
|
|
18
|
-
|
|
99
|
+
```tsx
|
|
100
|
+
import { Chat, XmppProvider } from '@ethora/chat-component';
|
|
19
101
|
|
|
20
|
-
|
|
102
|
+
export default function App() {
|
|
103
|
+
return (
|
|
104
|
+
<XmppProvider>
|
|
105
|
+
<Chat config={{ baseUrl: 'https://api.ethoradev.com/v1' }} />
|
|
106
|
+
</XmppProvider>
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
```
|
|
21
110
|
|
|
22
|
-
|
|
111
|
+
### 3. Run
|
|
23
112
|
|
|
24
|
-
|
|
113
|
+
```bash
|
|
114
|
+
npm run dev
|
|
115
|
+
```
|
|
25
116
|
|
|
26
|
-
|
|
27
|
-
2. specify a name for your project (e.g. "vite-project")
|
|
28
|
-
3. select framework and variant (for example, React -> Typescript but may be different depending on your project requirements, it will work with plain Javascript too)
|
|
117
|
+
Open `http://localhost:5173`.
|
|
29
118
|
|
|
30
|
-
|
|
119
|
+
Static reference screenshots:
|
|
31
120
|
|
|
32
|
-
|
|
121
|
+

|
|
122
|
+

|
|
123
|
+

|
|
33
124
|
|
|
34
|
-
|
|
35
|
-
5. npm i
|
|
36
|
-
6. npm i @ethora/chat-component
|
|
37
|
-
7. go to file src/App.tsx and replace it with the below code
|
|
125
|
+
### GIF placeholders (manual replacement)
|
|
38
126
|
|
|
39
|
-
|
|
40
|
-
import { Chat } from "@ethora/chat-component";
|
|
41
|
-
import "./App.css";
|
|
127
|
+
Replace each path with your recorded GIF file.
|
|
42
128
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
);
|
|
47
|
-
}
|
|
129
|
+
1. Install + first render
|
|
130
|
+
Target file: `img/placeholder-01-install-first-render.gif`
|
|
131
|
+

|
|
48
132
|
|
|
49
|
-
|
|
50
|
-
|
|
133
|
+
2. Login/auth flow
|
|
134
|
+
Target file: `img/placeholder-02-login-auth-flow.gif`
|
|
135
|
+

|
|
51
136
|
|
|
52
|
-
|
|
137
|
+
3. Room switching + messaging
|
|
138
|
+
Target file: `img/placeholder-03-room-switching-messaging.gif`
|
|
139
|
+

|
|
53
140
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
141
|
+
4. Push prompt + receive flow
|
|
142
|
+
Target file: `img/placeholder-04-push-flow.gif`
|
|
143
|
+

|
|
57
144
|
|
|
58
|
-
|
|
59
|
-
|
|
145
|
+
5. Widget customization before/after
|
|
146
|
+
Target file: `img/placeholder-05-widget-customization.gif`
|
|
147
|
+

|
|
60
148
|
|
|
61
|
-
|
|
149
|
+
6. Mobile responsive behavior
|
|
150
|
+
Target file: `img/placeholder-06-mobile-responsive.gif`
|
|
151
|
+

|
|
62
152
|
|
|
63
|
-
|
|
153
|
+
## Integration Modes
|
|
64
154
|
|
|
65
|
-
|
|
155
|
+
All modes below assume `XmppProvider` wraps `Chat`.
|
|
66
156
|
|
|
67
|
-
|
|
68
|
-
Leave this as is if you only need to demo or validate the chat functionality as part of your project.
|
|
69
|
-
If you need to have your own private chats, be able to login multiple users etc then go to https://www.ethora.com/, sign up in the top right which gives you a free account with Ethora backend where you can create your own App, manage your Users and Chats, view stats etc. Copy App ID & App Secret to your chat component code which will then switch to your own App context on the server side. The free tier is generous but should you need extra you can later build your own backend, upgrade to a paid tier from Ethora or use a self-hosted AWS marketplace image from Ethora.
|
|
157
|
+
### A) Minimal demo mode (provider + chat)
|
|
70
158
|
|
|
71
|
-
|
|
159
|
+
```tsx
|
|
160
|
+
<XmppProvider>
|
|
161
|
+
<Chat />
|
|
162
|
+
</XmppProvider>
|
|
163
|
+
```
|
|
72
164
|
|
|
73
|
-
|
|
165
|
+
Useful for local proof-of-concept and quick UI validation.
|
|
74
166
|
|
|
75
|
-
|
|
167
|
+
### B) Auto default credential fallback (legacy behavior)
|
|
76
168
|
|
|
77
|
-
|
|
78
|
-
|
|
169
|
+
If no `googleLogin`, no `jwtLogin`, no `userLogin`, and no `defaultLogin`, `LoginWrapper` currently triggers internal email/password fallback logic.
|
|
170
|
+
|
|
171
|
+
```tsx
|
|
172
|
+
<XmppProvider>
|
|
173
|
+
<Chat config={{ colors: { primary: '#2563eb', secondary: '#dbeafe' } }} />
|
|
174
|
+
</XmppProvider>
|
|
79
175
|
```
|
|
80
176
|
|
|
81
|
-
|
|
177
|
+
### C) Explicit email/password via `user` prop
|
|
82
178
|
|
|
179
|
+
```tsx
|
|
180
|
+
<XmppProvider>
|
|
181
|
+
<Chat
|
|
182
|
+
user={{
|
|
183
|
+
email: 'user@example.com',
|
|
184
|
+
password: 'PLACEHOLDER_PASSWORD',
|
|
185
|
+
}}
|
|
186
|
+
/>
|
|
187
|
+
</XmppProvider>
|
|
83
188
|
```
|
|
84
|
-
|
|
189
|
+
|
|
190
|
+
### D) Injected logged-in user (`userLogin`)
|
|
191
|
+
|
|
192
|
+
```tsx
|
|
193
|
+
<XmppProvider>
|
|
194
|
+
<Chat
|
|
85
195
|
config={{
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
196
|
+
userLogin: {
|
|
197
|
+
enabled: true,
|
|
198
|
+
user: {
|
|
199
|
+
_id: 'PLACEHOLDER_USER_ID',
|
|
200
|
+
appId: 'PLACEHOLDER_APP_ID',
|
|
201
|
+
walletAddress: 'PLACEHOLDER_WALLET_ADDRESS',
|
|
202
|
+
defaultWallet: { walletAddress: 'PLACEHOLDER_WALLET_ADDRESS' },
|
|
203
|
+
firstName: 'Jane',
|
|
204
|
+
lastName: 'Doe',
|
|
205
|
+
xmppPassword: 'PLACEHOLDER_XMPP_PASSWORD',
|
|
206
|
+
token: 'PLACEHOLDER_ACCESS_TOKEN',
|
|
207
|
+
refreshToken: 'PLACEHOLDER_REFRESH_TOKEN',
|
|
208
|
+
username: 'PLACEHOLDER_USERNAME',
|
|
209
|
+
},
|
|
210
|
+
},
|
|
94
211
|
}}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
212
|
+
/>
|
|
213
|
+
</XmppProvider>
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### E) JWT login
|
|
217
|
+
|
|
218
|
+
```tsx
|
|
219
|
+
<XmppProvider>
|
|
220
|
+
<Chat
|
|
221
|
+
config={{
|
|
222
|
+
jwtLogin: {
|
|
223
|
+
enabled: true,
|
|
224
|
+
token: 'PLACEHOLDER_JWT_TOKEN',
|
|
225
|
+
},
|
|
100
226
|
}}
|
|
101
|
-
roomJID=""
|
|
102
|
-
user={{ email: "", password: "" }}
|
|
103
|
-
disableHeader?: boolean;
|
|
104
|
-
|
|
105
|
-
disableRooms: boolean;
|
|
106
|
-
defaultLogin: boolean;
|
|
107
|
-
disableInteractions: boolean; //disable interactions
|
|
108
|
-
chatHeaderBurgerMenu: boolean; // disable burger menu in room header
|
|
109
|
-
roomListStyles: React.CSSProperties; // used to change room List styles (left)
|
|
110
|
-
chatRoomStyles: React.CSSProperties; // used to change room styles (right)
|
|
111
|
-
setRoomJidInPath: boolean; // used to set RoomId to url
|
|
112
227
|
/>
|
|
228
|
+
</XmppProvider>
|
|
113
229
|
```
|
|
114
230
|
|
|
115
|
-
|
|
231
|
+
### F) Google login
|
|
116
232
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
233
|
+
```tsx
|
|
234
|
+
<XmppProvider>
|
|
235
|
+
<Chat
|
|
236
|
+
config={{
|
|
237
|
+
googleLogin: {
|
|
238
|
+
enabled: true,
|
|
239
|
+
firebaseConfig: {
|
|
240
|
+
apiKey: 'PLACEHOLDER_API_KEY',
|
|
241
|
+
authDomain: 'PLACEHOLDER_AUTH_DOMAIN',
|
|
242
|
+
projectId: 'PLACEHOLDER_PROJECT_ID',
|
|
243
|
+
storageBucket: 'PLACEHOLDER_STORAGE_BUCKET',
|
|
244
|
+
messagingSenderId: 'PLACEHOLDER_MESSAGING_SENDER_ID',
|
|
245
|
+
appId: 'PLACEHOLDER_APP_ID',
|
|
246
|
+
},
|
|
247
|
+
},
|
|
248
|
+
}}
|
|
249
|
+
/>
|
|
250
|
+
</XmppProvider>
|
|
251
|
+
```
|
|
121
252
|
|
|
122
|
-
|
|
253
|
+
### G) Single-room entry + URL/QR behavior
|
|
123
254
|
|
|
255
|
+
```tsx
|
|
256
|
+
<XmppProvider>
|
|
257
|
+
<Chat
|
|
258
|
+
roomJID="ROOM_JID@conference.xmpp.ethoradev.com"
|
|
259
|
+
config={{
|
|
260
|
+
setRoomJidInPath: true,
|
|
261
|
+
qrUrl: 'https://your-app.example/chat/?qrChatId=',
|
|
262
|
+
}}
|
|
263
|
+
/>
|
|
264
|
+
</XmppProvider>
|
|
124
265
|
```
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
266
|
+
|
|
267
|
+
`roomJID` forces entry room.
|
|
268
|
+
`setRoomJidInPath` syncs room identity to URL path.
|
|
269
|
+
`useQRCodeChat` / `handleQRChatId` support QR/deep-link room opening.
|
|
270
|
+
|
|
271
|
+
## Behavior Notes and Legacy Quirks
|
|
272
|
+
|
|
273
|
+
- `newArch` is now default-on. If omitted, runtime uses new architecture paths.
|
|
274
|
+
- Old architecture is used only when you explicitly set `config.newArch = false`.
|
|
275
|
+
- `defaultLogin` currently has legacy inverted behavior in `LoginWrapper`:
|
|
276
|
+
- internal fallback login runs when login modes are not configured and `defaultLogin` is not set.
|
|
277
|
+
- keep this in mind when migrating; prefer explicit `userLogin` / `jwtLogin` / `googleLogin`.
|
|
278
|
+
|
|
279
|
+
## Chat Props Reference
|
|
280
|
+
|
|
281
|
+
These are the top-level props accepted by `Chat` (exported from `ReduxWrapper`).
|
|
282
|
+
|
|
283
|
+
| Prop | Type | Required | Notes |
|
|
284
|
+
| --- | --- | --- | --- |
|
|
285
|
+
| `config` | `IConfig` | No | Main behavior/configuration object. |
|
|
286
|
+
| `roomJID` | `string` | No | Force specific room JID on load. |
|
|
287
|
+
| `user` | `{ email: string; password: string }` | No | Credentials for email/password login helper path. |
|
|
288
|
+
| `loginData` | `{ email: string; password: string }` | No | Optional login payload. |
|
|
289
|
+
| `MainComponentStyles` | `React.CSSProperties` | No | Outer container style override. |
|
|
290
|
+
| `token` | `string` | No | Optional token input (legacy/integration-specific usage). |
|
|
291
|
+
| `CustomMessageComponent` | `React.ComponentType<MessageProps>` | No | Replace message bubble rendering. |
|
|
292
|
+
| `CustomInputComponent` | `React.ComponentType<SendInputProps & { onSendMessage?; onSendMedia?; placeholderText?; }>` | No | Replace chat input area. |
|
|
293
|
+
| `CustomScrollableArea` | `React.ComponentType<CustomScrollableAreaProps>` | No | Replace list/scroll wrapper behavior. |
|
|
294
|
+
| `CustomDaySeparator` | `React.ComponentType<DaySeparatorProps>` | No | Replace day separator node. |
|
|
295
|
+
| `CustomNewMessageLabel` | `React.ComponentType<NewMessageLabelProps>` | No | Replace "new message" marker. |
|
|
296
|
+
|
|
297
|
+
## Full Config Reference (`IConfig`)
|
|
298
|
+
|
|
299
|
+
Below is a grouped reference for all `config` options.
|
|
300
|
+
|
|
301
|
+
### Core
|
|
302
|
+
|
|
303
|
+
| Option | Type | Description |
|
|
304
|
+
| --- | --- | --- |
|
|
305
|
+
| `appId` | `string` | App identifier for backend context. |
|
|
306
|
+
| `baseUrl` | `string` | API base URL (default project uses `https://api.ethoradev.com/v1`). |
|
|
307
|
+
| `customAppToken` | `string` | Custom app token for API initialization. |
|
|
308
|
+
| `xmppSettings` | `{ devServer; host; conference?; xmppPingOnSendEnabled? }` | XMPP connectivity settings. |
|
|
309
|
+
| `initBeforeLoad` | `boolean` | Initialize XMPP before normal chat load flow. |
|
|
310
|
+
| `clearStoreBeforeInit` | `boolean` | Clear local store before initialization. |
|
|
311
|
+
| `newArch` | `boolean` | Defaults to `true`; set `false` to explicitly force legacy/old architecture paths. |
|
|
312
|
+
| `useStoreConsoleEnabled` | `boolean` | Enable verbose internal logging in console. |
|
|
313
|
+
|
|
314
|
+
### UI and Layout
|
|
315
|
+
|
|
316
|
+
| Option | Type | Description |
|
|
317
|
+
| --- | --- | --- |
|
|
318
|
+
| `disableHeader` | `boolean` | Hide chat header. |
|
|
319
|
+
| `disableMedia` | `boolean` | Disable media sending/processing paths. |
|
|
320
|
+
| `disableRooms` | `boolean` | Hide/disable room list area. |
|
|
321
|
+
| `disableRoomMenu` | `boolean` | Disable room menu controls. |
|
|
322
|
+
| `disableRoomConfig` | `boolean` | Disable room configuration actions. |
|
|
323
|
+
| `disableNewChatButton` | `boolean` | Hide new chat/create room action. |
|
|
324
|
+
| `disableUserCount` | `boolean` | Hide user count in header/UI. |
|
|
325
|
+
| `disableChatInfo` | `{ disableHeader?; disableDescription?; disableType?; disableMembers?; hideMembers?; disableChatHeaderMenu? }` | Fine-grained chat info panel toggles. |
|
|
326
|
+
| `chatHeaderBurgerMenu` | `boolean` | Toggle burger menu in chat header. |
|
|
327
|
+
| `chatHeaderSettings` | `{ hide?; disableCreate?; disableMenu?; hideSearch? }` | Additional header-level controls. |
|
|
328
|
+
| `chatHeaderAdditional` | `{ enabled: boolean; element: any }` | Inject custom element into header area. |
|
|
329
|
+
| `headerLogo` | `string \| React.ReactElement` | Custom logo in header. |
|
|
330
|
+
| `headerMenu` | `() => void` | Custom menu handler. |
|
|
331
|
+
| `headerChatMenu` | `() => void` | Custom room header menu handler. |
|
|
332
|
+
| `colors` | `{ primary: string; secondary: string }` | Theme colors for component UI. |
|
|
333
|
+
| `roomListStyles` | `React.CSSProperties` | Styles for room list pane. |
|
|
334
|
+
| `chatRoomStyles` | `React.CSSProperties` | Styles for chat pane. |
|
|
335
|
+
| `backgroundChat` | `{ color?: string; image?: string \| File }` | Chat background customization. |
|
|
336
|
+
| `bubleMessage` | `MessageBubble` | Bubble-level style overrides (as defined in types). |
|
|
337
|
+
| `setRoomJidInPath` | `boolean` | Sync room JID to URL path. |
|
|
338
|
+
| `qrUrl` | `string` | Base URL for QR deep link behavior. |
|
|
339
|
+
|
|
340
|
+
### Auth and Identity
|
|
341
|
+
|
|
342
|
+
| Option | Type | Description |
|
|
343
|
+
| --- | --- | --- |
|
|
344
|
+
| `defaultLogin` | `boolean` | Legacy quirk: current runtime fallback behavior is inverted; see Behavior Notes section. |
|
|
345
|
+
| `googleLogin` | `{ enabled: boolean; firebaseConfig: FBConfig }` | Google login support via Firebase config. |
|
|
346
|
+
| `jwtLogin` | `{ token: string; enabled: boolean; handleBadlogin?: React.ReactElement }` | Log user in using JWT exchange flow. |
|
|
347
|
+
| `userLogin` | `{ enabled: boolean; user: User \| null }` | Inject already-authenticated user directly. |
|
|
348
|
+
| `customLogin` | `{ enabled: boolean; loginFunction: () => Promise<User \| null> }` | Provide your custom async login function. |
|
|
349
|
+
| `refreshTokens` | `{ enabled: boolean; refreshFunction?: () => Promise<{ accessToken: string; refreshToken?: string } \| null> }` | Token refresh strategy. |
|
|
350
|
+
|
|
351
|
+
### Rooms and Data
|
|
352
|
+
|
|
353
|
+
| Option | Type | Description |
|
|
354
|
+
| --- | --- | --- |
|
|
355
|
+
| `defaultRooms` | `ConfigRoom[]` | Seed/default rooms. |
|
|
356
|
+
| `customRooms` | `{ rooms: PartialRoomWithMandatoryKeys[]; disableGetRooms?: boolean; singleRoom: boolean }` | Fully controlled room source. |
|
|
357
|
+
| `forceSetRoom` | `boolean` | Force room setup path in init flow. |
|
|
358
|
+
| `enableRoomsRetry` | `{ enabled: boolean; helperText: string }` | Enable retry UX when rooms fail to load. |
|
|
359
|
+
|
|
360
|
+
### Messaging and Interactions
|
|
361
|
+
|
|
362
|
+
| Option | Type | Description |
|
|
363
|
+
| --- | --- | --- |
|
|
364
|
+
| `disableInteractions` | `boolean` | Disable message interaction menu/actions. |
|
|
365
|
+
| `disableProfilesInteractions` | `boolean` | Disable profile interactions from chat UI. |
|
|
366
|
+
| `disableSentLogic` | `boolean` | Disable default sent-state logic when needed. |
|
|
367
|
+
| `secondarySendButton` | `{ enabled: boolean; messageEdit: string; label?: React.ReactNode; buttonStyles?: React.CSSProperties; hideInputSendButton?: boolean; overwriteEnterClick?: true }` | Extra send action/button config. |
|
|
368
|
+
| `botMessageAutoScroll` | `boolean` | Force auto-scroll behavior on bot messages. |
|
|
369
|
+
| `messageTextFilter` | `{ enabled: boolean; filterFunction: (text: string) => string }` | Transform/filter outgoing message text. |
|
|
370
|
+
| `eventHandlers` | `{ onMessageSent?; onMessageFailed?; onMessageEdited? }` | Lifecycle callbacks for message operations. |
|
|
371
|
+
| `translates` | `{ enabled: boolean; translations?: Iso639_1Codes }` | Message translation-related options. |
|
|
372
|
+
| `whitelistSystemMessage` | `string[]` | Restrict/render only selected system message types. |
|
|
373
|
+
| `customSystemMessage` | `React.ComponentType<MessageProps>` | Replace system message component renderer. |
|
|
374
|
+
|
|
375
|
+
### Typing and Sending Control
|
|
376
|
+
|
|
377
|
+
| Option | Type | Description |
|
|
378
|
+
| --- | --- | --- |
|
|
379
|
+
| `disableTypingIndicator` | `boolean` | Disable typing indicator UI logic. |
|
|
380
|
+
| `customTypingIndicator` | `{ enabled: boolean; text?: string \| ((usersTyping: string[]) => string); position?: 'bottom' \| 'top' \| 'overlay' \| 'floating'; styles?: React.CSSProperties; customComponent?: React.ComponentType<{ usersTyping: string[]; text: string; isVisible: boolean; }> }` | Customize typing indicator content and rendering. |
|
|
381
|
+
| `blockMessageSendingWhenProcessing` | `boolean \| { enabled: boolean; timeout?: number; onTimeout?: (roomJID: string) => void }` | Gate sends while processing in-flight state. |
|
|
382
|
+
|
|
383
|
+
### Notifications
|
|
384
|
+
|
|
385
|
+
| Option | Type | Description |
|
|
386
|
+
| --- | --- | --- |
|
|
387
|
+
| `inAppNotifications` | `{ enabled?; showInContext?; position?; maxNotifications?; duration?; onClick?; customComponent? }` | In-app toast notification behavior and custom rendering. |
|
|
388
|
+
|
|
389
|
+
### Push
|
|
390
|
+
|
|
391
|
+
| Option | Type | Description |
|
|
392
|
+
| --- | --- | --- |
|
|
393
|
+
| `pushNotifications.enabled` | `boolean` | Enable browser push subscription flow. |
|
|
394
|
+
| `pushNotifications.vapidPublicKey` | `string` | VAPID public key for push registration. |
|
|
395
|
+
| `pushNotifications.firebaseConfig` | `FBConfig` | Firebase app config for push messaging. |
|
|
396
|
+
| `pushNotifications.serviceWorkerPath` | `string` | Service worker path, default `/firebase-messaging-sw.js`. |
|
|
397
|
+
| `pushNotifications.serviceWorkerScope` | `string` | Service worker scope, default `/`. |
|
|
398
|
+
| `pushNotifications.softAsk` | `boolean` | Do not immediately trigger browser permission prompt. |
|
|
399
|
+
|
|
400
|
+
## Custom Widgets and Overrides
|
|
401
|
+
|
|
402
|
+
You can replace key UI parts without forking the package.
|
|
403
|
+
|
|
404
|
+
| Override prop | Purpose |
|
|
405
|
+
| --- | --- |
|
|
406
|
+
| `CustomMessageComponent` | Fully custom message bubble/row rendering. |
|
|
407
|
+
| `CustomInputComponent` | Custom composer and send controls. |
|
|
408
|
+
| `CustomScrollableArea` | Custom scroll/list container (virtualized or custom behavior). |
|
|
409
|
+
| `CustomDaySeparator` | Custom date separator component. |
|
|
410
|
+
| `CustomNewMessageLabel` | Custom "new message" divider label. |
|
|
411
|
+
|
|
412
|
+
Example:
|
|
413
|
+
|
|
414
|
+
```tsx
|
|
415
|
+
import { Chat } from '@ethora/chat-component';
|
|
416
|
+
import CustomMessageBubble from './CustomMessageBubble';
|
|
417
|
+
import CustomChatInput from './CustomChatInput';
|
|
418
|
+
import CustomScrollableArea from './CustomScrollableArea';
|
|
419
|
+
import CustomDaySeparator from './CustomDaySeparator';
|
|
420
|
+
import CustomNewMessageLabel from './CustomNewMessageLabel';
|
|
421
|
+
|
|
422
|
+
export default function App() {
|
|
423
|
+
return (
|
|
424
|
+
<Chat
|
|
425
|
+
CustomMessageComponent={CustomMessageBubble}
|
|
426
|
+
CustomInputComponent={CustomChatInput}
|
|
427
|
+
CustomScrollableArea={CustomScrollableArea}
|
|
428
|
+
CustomDaySeparator={CustomDaySeparator}
|
|
429
|
+
CustomNewMessageLabel={CustomNewMessageLabel}
|
|
430
|
+
config={{
|
|
431
|
+
colors: { primary: '#1d4ed8', secondary: '#dbeafe' },
|
|
432
|
+
}}
|
|
433
|
+
/>
|
|
434
|
+
);
|
|
129
435
|
}
|
|
130
436
|
```
|
|
131
437
|
|
|
132
|
-
|
|
438
|
+
Reference example components in repository:
|
|
439
|
+
|
|
440
|
+
- `src/examples/customComponents/CustomMessageBubble.tsx`
|
|
441
|
+
- `src/examples/customComponents/CustomChatInput.tsx`
|
|
442
|
+
- `src/examples/customComponents/CustomScrollableArea.tsx`
|
|
443
|
+
- `src/examples/customComponents/CustomDaySeparator.tsx`
|
|
444
|
+
- `src/examples/customComponents/CustomNewMessageLabel.tsx`
|
|
445
|
+
|
|
446
|
+
## Push Notifications
|
|
447
|
+
|
|
448
|
+
### Prerequisites
|
|
449
|
+
|
|
450
|
+
| Requirement | Why |
|
|
451
|
+
| --- | --- |
|
|
452
|
+
| HTTPS origin (or localhost) | Browser push APIs require secure contexts. |
|
|
453
|
+
| Firebase project | FCM token + push transport setup. |
|
|
454
|
+
| VAPID public key | Required for web push subscription. |
|
|
455
|
+
| Service worker file | Required for background notification handling. |
|
|
456
|
+
|
|
457
|
+
### Setup steps
|
|
133
458
|
|
|
459
|
+
1. Copy service worker into your app's public assets:
|
|
460
|
+
|
|
461
|
+
```bash
|
|
462
|
+
npx @ethora/chat-component ethora-chat
|
|
134
463
|
```
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
464
|
+
|
|
465
|
+
2. Configure push in `config`:
|
|
466
|
+
|
|
467
|
+
```tsx
|
|
468
|
+
<Chat
|
|
469
|
+
config={{
|
|
470
|
+
pushNotifications: {
|
|
471
|
+
enabled: true,
|
|
472
|
+
vapidPublicKey: 'PLACEHOLDER_VAPID_PUBLIC_KEY',
|
|
473
|
+
firebaseConfig: {
|
|
474
|
+
apiKey: 'PLACEHOLDER_API_KEY',
|
|
475
|
+
authDomain: 'PLACEHOLDER_AUTH_DOMAIN',
|
|
476
|
+
projectId: 'PLACEHOLDER_PROJECT_ID',
|
|
477
|
+
storageBucket: 'PLACEHOLDER_STORAGE_BUCKET',
|
|
478
|
+
messagingSenderId: 'PLACEHOLDER_MESSAGING_SENDER_ID',
|
|
479
|
+
appId: 'PLACEHOLDER_APP_ID',
|
|
480
|
+
},
|
|
481
|
+
serviceWorkerPath: '/firebase-messaging-sw.js',
|
|
482
|
+
serviceWorkerScope: '/',
|
|
483
|
+
softAsk: false,
|
|
484
|
+
},
|
|
485
|
+
}}
|
|
486
|
+
/>
|
|
143
487
|
```
|
|
144
488
|
|
|
145
|
-
|
|
489
|
+
3. Optional: use hook directly for controlled permission flow:
|
|
146
490
|
|
|
147
|
-
|
|
491
|
+
```tsx
|
|
492
|
+
import { usePushNotifications } from '@ethora/chat-component';
|
|
148
493
|
|
|
149
|
-
|
|
494
|
+
function PushPermissionButton() {
|
|
495
|
+
const { requestPermission } = usePushNotifications({
|
|
496
|
+
enabled: true,
|
|
497
|
+
softAsk: true,
|
|
498
|
+
vapidPublicKey: 'PLACEHOLDER_VAPID_PUBLIC_KEY',
|
|
499
|
+
});
|
|
150
500
|
|
|
151
|
-
|
|
501
|
+
return <button onClick={() => requestPermission()}>Enable Push</button>;
|
|
502
|
+
}
|
|
503
|
+
```
|
|
152
504
|
|
|
153
|
-
|
|
505
|
+
## Auth Strategies
|
|
154
506
|
|
|
155
|
-
|
|
156
|
-
|
|
507
|
+
| Strategy | Config shape | Best for |
|
|
508
|
+
| --- | --- | --- |
|
|
509
|
+
| Default fallback (legacy quirk) | no auth block / `defaultLogin` | Legacy/demo flows; prefer explicit auth modes in production |
|
|
510
|
+
| Injected user | `userLogin: { enabled: true, user }` | App already has authenticated user/session |
|
|
511
|
+
| JWT login | `jwtLogin: { enabled: true, token }` | Token-based backend auth flow |
|
|
512
|
+
| Google login | `googleLogin: { enabled: true, firebaseConfig }` | Google SSO using Firebase |
|
|
513
|
+
| Custom login function | `customLogin: { enabled: true, loginFunction }` | Fully custom identity provider |
|
|
157
514
|
|
|
158
|
-
|
|
515
|
+
### Example: injected user (bypass login screen)
|
|
159
516
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
517
|
+
```tsx
|
|
518
|
+
<Chat
|
|
519
|
+
config={{
|
|
520
|
+
userLogin: {
|
|
521
|
+
enabled: true,
|
|
522
|
+
user: {
|
|
523
|
+
_id: 'PLACEHOLDER_USER_ID',
|
|
524
|
+
appId: 'PLACEHOLDER_APP_ID',
|
|
525
|
+
walletAddress: 'PLACEHOLDER_WALLET_ADDRESS',
|
|
526
|
+
defaultWallet: { walletAddress: 'PLACEHOLDER_WALLET_ADDRESS' },
|
|
527
|
+
firstName: 'Jane',
|
|
528
|
+
lastName: 'Doe',
|
|
529
|
+
xmppPassword: 'PLACEHOLDER_XMPP_PASSWORD',
|
|
530
|
+
token: 'PLACEHOLDER_ACCESS_TOKEN',
|
|
531
|
+
refreshToken: 'PLACEHOLDER_REFRESH_TOKEN',
|
|
532
|
+
username: 'PLACEHOLDER_USERNAME',
|
|
533
|
+
},
|
|
534
|
+
},
|
|
535
|
+
}}
|
|
536
|
+
/>
|
|
537
|
+
```
|
|
163
538
|
|
|
164
|
-
|
|
539
|
+
### Example: JWT login
|
|
165
540
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
541
|
+
```tsx
|
|
542
|
+
<Chat
|
|
543
|
+
config={{
|
|
544
|
+
jwtLogin: {
|
|
545
|
+
enabled: true,
|
|
546
|
+
token: 'PLACEHOLDER_JWT_TOKEN',
|
|
547
|
+
},
|
|
548
|
+
refreshTokens: {
|
|
549
|
+
enabled: true,
|
|
550
|
+
refreshFunction: async () => {
|
|
551
|
+
return {
|
|
552
|
+
accessToken: 'PLACEHOLDER_NEW_ACCESS_TOKEN',
|
|
553
|
+
refreshToken: 'PLACEHOLDER_NEW_REFRESH_TOKEN',
|
|
554
|
+
};
|
|
555
|
+
},
|
|
556
|
+
},
|
|
557
|
+
}}
|
|
558
|
+
/>
|
|
559
|
+
```
|
|
170
560
|
|
|
171
|
-
|
|
561
|
+
## Hooks and API Exports
|
|
562
|
+
|
|
563
|
+
| Export | Type | Purpose |
|
|
564
|
+
| --- | --- | --- |
|
|
565
|
+
| `Chat` | React component | Main chat component. |
|
|
566
|
+
| `XmppProvider` | React provider | Provides XMPP client context for internal hooks/state. |
|
|
567
|
+
| `useUnread` | hook | Returns unread counters. |
|
|
568
|
+
| `logoutService` | service | Programmatic logout utility. |
|
|
569
|
+
| `useQRCodeChat` | hook | Handle QR-based room links. |
|
|
570
|
+
| `handleQRChatId` | function | Parse/process QR chat ID from URL. |
|
|
571
|
+
| `useInAppNotifications` | hook | Enables and handles in-app notifications. |
|
|
572
|
+
| `usePushNotifications` | hook | Push subscription + foreground handling workflow. |
|
|
573
|
+
| `resendMessage` | function | Retry sending failed/pending messages. |
|
|
574
|
+
|
|
575
|
+
Basic hook usage:
|
|
576
|
+
|
|
577
|
+
```tsx
|
|
578
|
+
import { useUnread, logoutService } from '@ethora/chat-component';
|
|
579
|
+
|
|
580
|
+
function HeaderActions() {
|
|
581
|
+
const { totalCount } = useUnread();
|
|
582
|
+
|
|
583
|
+
return (
|
|
584
|
+
<div>
|
|
585
|
+
<span>Unread: {totalCount}</span>
|
|
586
|
+
<button onClick={() => logoutService.performLogout()}>Logout</button>
|
|
587
|
+
</div>
|
|
588
|
+
);
|
|
589
|
+
}
|
|
590
|
+
```
|
|
172
591
|
|
|
173
|
-
|
|
592
|
+
`logoutService.performLogout()` behavior:
|
|
174
593
|
|
|
175
|
-
-
|
|
176
|
-
-
|
|
594
|
+
- Dispatches `chatSettingStore/logout`
|
|
595
|
+
- Dispatches `rooms/setLogoutState`
|
|
596
|
+
- Dispatches `roomHeap/clearHeap`
|
|
597
|
+
- Triggers logout middleware, which emits `ethora-xmpp-logout`
|
|
598
|
+
- `XmppProvider` listens to that event and disconnects active XMPP client
|
|
177
599
|
|
|
178
|
-
|
|
600
|
+
## Use Cases and Feature Coverage
|
|
179
601
|
|
|
180
|
-
|
|
181
|
-
|
|
602
|
+
| Area | Status in this package |
|
|
603
|
+
| --- | --- |
|
|
604
|
+
| One-room embedded chat | Available |
|
|
605
|
+
| Multi-room chat UI | Available |
|
|
606
|
+
| Message interactions (reply/copy/edit/delete/report/reactions) | Available |
|
|
607
|
+
| Typing indicator | Available |
|
|
608
|
+
| Profile interactions in chat | Available (can be disabled) |
|
|
609
|
+
| File/media attachments | Available with ongoing enhancements |
|
|
610
|
+
| In-app notifications | Available |
|
|
611
|
+
| Web push notifications | Available |
|
|
612
|
+
| Wallet/assets and extended social modules | Primarily in full Ethora platform |
|
|
182
613
|
|
|
183
|
-
|
|
614
|
+
## Hosted vs Self-Host Guidance
|
|
184
615
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
-
|
|
188
|
-
-
|
|
189
|
-
|
|
616
|
+
| Model | Best for | Pros | Tradeoffs |
|
|
617
|
+
| --- | --- | --- | --- |
|
|
618
|
+
| Hosted Ethora backend | Fast time-to-market, smaller teams, MVPs | Fast setup, managed backend operations, easier push/auth onboarding | Less infrastructure-level control |
|
|
619
|
+
| Self-hosted Ethora stack | Regulated environments, deep infra control | Full control over infrastructure, compliance customization, internal network deployment options | Higher DevOps/maintenance overhead |
|
|
620
|
+
| Hybrid | Gradual migration or split workloads | Can start fast and migrate critical paths later | More architecture complexity |
|
|
190
621
|
|
|
191
|
-
#### Message interactions
|
|
192
622
|
|
|
193
|
-
|
|
194
|
-
- **Emoji Reactions** ✅ - Users are able to long tap / click on the message and send Emoji reactions to the message. Reactions are displayed in the corner of the message bubble.
|
|
623
|
+
## Feature Roadmap
|
|
195
624
|
|
|
196
|
-
|
|
625
|
+
This is a practical planning snapshot for cross-platform consumers. It is not a release commitment.
|
|
197
626
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
627
|
+
| Surface | Current state | Notes |
|
|
628
|
+
| --- | --- | --- |
|
|
629
|
+
| Web React (`@ethora/chat-component`) | Available now | This repository. |
|
|
630
|
+
| React Native | Via broader Ethora stack | Track platform-specific implementation in Ethora repos/docs. |
|
|
631
|
+
| Swift (iOS native) | Planned / ecosystem-level | Confirm status with Ethora team for production timelines. |
|
|
632
|
+
| Kotlin (Android native) | Planned / ecosystem-level | Confirm status with Ethora team for production timelines. |
|
|
633
|
+
| Flutter | Planned / ecosystem-level | Confirm status with Ethora team for production timelines. |
|
|
634
|
+
| Additional roadmap items | Ongoing | Media improvements, richer profile/wallet experiences, broader integration guides. |
|
|
202
635
|
|
|
203
|
-
|
|
636
|
+
## Troubleshooting
|
|
204
637
|
|
|
205
|
-
|
|
638
|
+
| Issue | Likely cause | Fix |
|
|
639
|
+
| --- | --- | --- |
|
|
640
|
+
| `useXmppClient must be used within an XmppProvider` | Using internal XMPP-dependent logic without provider context | Wrap the app tree with `XmppProvider` where needed. |
|
|
641
|
+
| Chat loads but no rooms appear | Auth/app context mismatch or room fetching restrictions | Verify `appId`, user credentials/tokens, `baseUrl`, and `customRooms` settings. |
|
|
642
|
+
| Push permission never appears | `softAsk: true` without manual trigger, insecure origin, or missing VAPID key | Trigger `requestPermission()`, use HTTPS/localhost, set valid VAPID key. |
|
|
643
|
+
| Service worker not found | `firebase-messaging-sw.js` missing in public dir | Run `npx @ethora/chat-component ethora-chat` or copy file manually. |
|
|
644
|
+
| Login loop / auth failure | Wrong token/user object shape | Validate `jwtLogin`, `userLogin.user`, and refresh token flow. |
|
|
206
645
|
|
|
207
|
-
|
|
646
|
+
## Ethora Links and Support
|
|
647
|
+
### Product
|
|
208
648
|
|
|
209
|
-
-
|
|
649
|
+
- Website: https://ethora.com/
|
|
650
|
+
- Try Ethora: https://app.ethora.com/register
|
|
210
651
|
|
|
211
|
-
###
|
|
652
|
+
### Developer Docs
|
|
212
653
|
|
|
213
|
-
-
|
|
214
|
-
-
|
|
215
|
-
-
|
|
216
|
-
-
|
|
217
|
-
-
|
|
218
|
-
-
|
|
654
|
+
- Chat component docs: https://docs.ethora.com/
|
|
655
|
+
- Ethora GitHub hub: https://github.com/dappros/ethora
|
|
656
|
+
- This package repo: https://github.com/dappros/ethora-chat-component
|
|
657
|
+
- Ethora GitHub organization: https://github.com/dappros
|
|
658
|
+
- API docs (public): https://app.dappros.com/api-docs/
|
|
659
|
+
- API docs (environment used in this repo): https://api.ethoradev.com/api-docs
|
|
219
660
|
|
|
220
|
-
|
|
661
|
+
### Community and Support
|
|
221
662
|
|
|
222
|
-
-
|
|
663
|
+
- Forum: https://forum.ethora.com/
|
|
223
664
|
- Discord: https://discord.gg/Sm6bAHA3ZC
|
|
224
|
-
- Contact
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
665
|
+
- Contact: https://ethora.com/#contact
|
|
666
|
+
|
|
667
|
+
## License
|
|
668
|
+
|
|
669
|
+
AGPL. See [LICENSE.txt](./LICENSE.txt).
|