@tellescope/chat 1.3.4 → 1.3.5

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tellescope/chat",
3
- "version": "1.3.4",
3
+ "version": "1.3.5",
4
4
  "description": "",
5
5
  "main": "./lib/cjs/index.js",
6
6
  "module": "./lib/esm/index.js",
@@ -35,7 +35,7 @@
35
35
  "@mui/icons-material": "^5.0.1",
36
36
  "@mui/material": "^5.0.2",
37
37
  "@tellescope/constants": "^1.3.3",
38
- "@tellescope/react-components": "^1.3.4",
38
+ "@tellescope/react-components": "^1.3.5",
39
39
  "@tellescope/sdk": "^1.3.3",
40
40
  "@tellescope/types-client": "^1.3.3",
41
41
  "@tellescope/types-models": "^1.3.3",
@@ -51,7 +51,7 @@
51
51
  "react": "^16.8.0 || ^17.0.0 || ^18.0.0",
52
52
  "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
53
53
  },
54
- "gitHead": "1339d078ebf1d30830b2445639fe6357878178c4",
54
+ "gitHead": "840b57b6260a5de2f5785b8495cd4954a240a014",
55
55
  "publishConfig": {
56
56
  "access": "public"
57
57
  }
package/src/chat.tsx CHANGED
@@ -20,6 +20,9 @@ import {
20
20
  SecureImage,
21
21
  ImageDimensions,
22
22
  SecureVideo,
23
+ useUsers,
24
+ useEndusers,
25
+ useUserAndEnduserDisplayInfo,
23
26
  } from "@tellescope/react-components"
24
27
 
25
28
  import {
@@ -141,8 +144,8 @@ export const Message = ({
141
144
  const session = useResolvedSession()
142
145
  const chatUserId = session.userInfo.id
143
146
 
144
- const [displayInfo] = useChatRoomDisplayInfo(message.roomId)
145
- const displayInfoLookup = value_is_loaded(displayInfo) ? displayInfo.value : {} as ChatRoomDisplayInfo
147
+ const [usersLoading] = useUsers()
148
+ const [endusersLoading] = useEndusers()
146
149
 
147
150
  // deep copy so that the override of background color doesn't affect other messages
148
151
  const textBGStyle = { ...message.senderId === chatUserId ? sentMessageStyle : receivedMessageStyle }
@@ -190,7 +193,11 @@ export const Message = ({
190
193
  const displayPicture = (
191
194
  <DisplayPicture
192
195
  style={{ maxWidth: '10%' }}
193
- user={displayInfoLookup[message.senderId ?? ''] ?? { id: message.senderId, avatar: '' }}
196
+ user={
197
+ (session.userInfo.id === message.senderId ? session.userInfo : undefined)
198
+ || (value_is_loaded(usersLoading) ? usersLoading.value.find(u => u.id === message.senderId) : undefined)
199
+ || (value_is_loaded(endusersLoading) ? endusersLoading.value.find(e => e.id === message.senderId) : undefined)
200
+ }
194
201
  size={iconSize}
195
202
  />
196
203
  )
@@ -475,4 +482,24 @@ export const UserActiveBadge = ({ user, style, size, activeThresholdMS, inactive
475
482
  return (
476
483
  <Badge color={defaultColorForStatus[status]} size={size} style={style}/>
477
484
  )
485
+ }
486
+
487
+ export const AttendeesList = ({ roomId, style, attendeeStyle } : { roomId: string, attendeeStyle?: React.CSSProperties } & Styled) => {
488
+ const [, { findById: findRoom } ] = useChatRooms({ dontFetch: true })
489
+ const displayInfo = useUserAndEnduserDisplayInfo()
490
+
491
+ const room = findRoom(roomId)
492
+ if (!room) return null
493
+
494
+ if (!(room.enduserIds?.length || room.userIds?.length )) throw new Error("This room has no users or endusers")
495
+
496
+ return (
497
+ <Flex flex={1} column style={style}>
498
+ {[...room.userIds ?? [], ...room.enduserIds ?? []].map(id => (
499
+ <Typography style={{ fontSize: 18, narginBottom: 10, ...attendeeStyle }}>
500
+ {user_display_name(displayInfo[id])}
501
+ </Typography>
502
+ ))}
503
+ </Flex>
504
+ )
478
505
  }
@@ -1,6 +1,6 @@
1
1
  import { launchImageLibrary, launchCamera } from 'react-native-image-picker';
2
2
  import { Modal, View, TextInput } from "react-native"
3
- import { Avatar } from 'react-native-paper'
3
+ import { Avatar, RadioButton } from 'react-native-paper'
4
4
  import {
5
5
  useFileUpload,
6
6
  Flex,
@@ -11,9 +11,19 @@ import {
11
11
  LabeledIconButton,
12
12
  Button,
13
13
  Paper,
14
- useChats,
14
+ useChats,
15
+ useUsers,
16
+ useEndusers,
17
+ List,
18
+ LoadingData,
19
+ useChatRooms,
20
+ APIError,
21
+ LoadingButton,
15
22
  } from "@tellescope/react-components"
16
23
  import { useState } from 'react';
24
+ import { ChatRoom } from '@tellescope/types-client';
25
+ import { render } from 'react-dom';
26
+ import { user_display_name } from '@tellescope/utilities';
17
27
 
18
28
  const CHAT_ICON_SIZE = 35
19
29
  const SendImageOrVideo = ({
@@ -171,4 +181,93 @@ export const SendMessage = ({
171
181
  </Flex>
172
182
  </Flex>
173
183
  )
184
+ }
185
+
186
+ export interface CreateGroupChatProps {
187
+ excludeEndusers?: boolean,
188
+ excludeUsers?: boolean,
189
+ onGoBack?: () => void,
190
+ onSuccess?: (c: ChatRoom) => void,
191
+ onError?: (e: APIError) => void,
192
+ roomTitle?: string,
193
+ }
194
+ export const CreateGroupChat = ({
195
+ excludeEndusers,
196
+ excludeUsers,
197
+ onGoBack,
198
+ onSuccess,
199
+ onError=console.error,
200
+ roomTitle="Group Chat"
201
+ }: CreateGroupChatProps) => {
202
+ const [, { createElement: createRoom }] = useChatRooms()
203
+ const [endusersLoading] = useEndusers()
204
+ const [usersLoading] = useUsers()
205
+
206
+ const [selected, setSelected] = useState<string[]>([])
207
+
208
+ return (
209
+ <LoadingData data={{ endusers: endusersLoading, users: usersLoading }} render={({ users, endusers }) => (
210
+ <Flex flex={1} column>
211
+ <Flex alignItems="center" justifyContent={"space-between"} style={{
212
+ marginBottom: 10,
213
+ }}>
214
+ {onGoBack &&
215
+ <Button onClick={onGoBack}>
216
+ Back
217
+ </Button>
218
+ }
219
+ <Typography style={{ fontSize: 20, textAlign: 'center' }}>
220
+ Select Members
221
+ </Typography>
222
+
223
+ <LoadingButton submitText='Create' submittingText='Create'
224
+ disabled={selected.length === 0}
225
+ style={{ display: 'flex', marginRight: 5 }}
226
+ onClick={() => {
227
+ const userIds = selected.filter(s => users.find(u => u.id === s))
228
+ const enduserIds = selected.filter(s => endusers.find(u => u.id === s))
229
+
230
+ createRoom({
231
+ enduserIds,
232
+ userIds,
233
+ title: roomTitle,
234
+ })
235
+ .then(r => {
236
+ setSelected([])
237
+ onSuccess?.(r)
238
+ })
239
+ .catch(onError)
240
+ }}
241
+ />
242
+ </Flex>
243
+
244
+ <List items={[...excludeUsers ? [] : users, ... excludeEndusers ? [] : endusers]} render={user => (
245
+ <Paper flex elevation={5} style={{
246
+ marginBottom: 2,
247
+ }}>
248
+ <Flex flex={1} alignItems="center" justifyContent="space-between"
249
+ onClick={() => setSelected(ss => (
250
+ ss.includes(user.id)
251
+ ? ss.filter(s => s !== user.id)
252
+ : [user.id, ...ss]
253
+ ))}
254
+ style={{
255
+ paddingLeft: 5, paddingRight: 5,
256
+ }}
257
+ >
258
+ <RadioButton value={user.id}
259
+ status={selected.includes(user.id) ? 'checked' : 'unchecked'}
260
+ />
261
+
262
+ <Typography style={{
263
+ fontWeight: selected.includes(user.id) ? 'bold' : undefined,
264
+ }}>
265
+ {user_display_name(user)}
266
+ </Typography>
267
+ </Flex>
268
+ </Paper>
269
+ )} />
270
+ </Flex>
271
+ )} />
272
+ )
174
273
  }