@tellescope/chat 0.0.5 → 0.0.9

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": "0.0.5",
3
+ "version": "0.0.9",
4
4
  "description": "",
5
5
  "main": "./lib/cjs/index.js",
6
6
  "module": "./lib/esm/index.js",
@@ -34,11 +34,12 @@
34
34
  "@mui/icons-material": "^5.0.1",
35
35
  "@mui/material": "^5.0.2",
36
36
  "@tellescope/authentication": "^0.0.5",
37
- "@tellescope/constants": "^0.0.5",
38
- "@tellescope/react-components": "^0.0.5",
39
- "@tellescope/sdk": "^0.0.5",
40
- "@tellescope/types-client": "^0.0.5",
41
- "@tellescope/types-utilities": "^0.0.5",
37
+ "@tellescope/constants": "^0.0.9",
38
+ "@tellescope/react-components": "^0.0.9",
39
+ "@tellescope/sdk": "^0.0.9",
40
+ "@tellescope/types-client": "^0.0.9",
41
+ "@tellescope/types-utilities": "^0.0.9",
42
+ "@tellescope/utilities": "^0.0.9",
42
43
  "@typescript-eslint/eslint-plugin": "^4.33.0",
43
44
  "@typescript-eslint/parser": "^4.33.0",
44
45
  "eslint": "^7.32.0",
@@ -49,7 +50,7 @@
49
50
  "react": "^17.0.2",
50
51
  "react-dom": "^17.0.2"
51
52
  },
52
- "gitHead": "42d964a504257ae89927b984ace7495f26ce72e7",
53
+ "gitHead": "267964c111ed9747bcb81c720b8d6c393e196089",
53
54
  "publishConfig": {
54
55
  "access": "public"
55
56
  }
package/src/chat.tsx ADDED
@@ -0,0 +1,301 @@
1
+ import React, { useCallback, useState, CSSProperties } from "react"
2
+
3
+ import {
4
+ List,
5
+ Flex,
6
+ } from "@tellescope/react-components/lib/esm/layout"
7
+ import {
8
+ AsyncIconButton,
9
+ } from "@tellescope/react-components/lib/esm/controls"
10
+ import {
11
+ SendIcon,
12
+ Styled,
13
+ Typography,
14
+ TextField,
15
+ } from "@tellescope/react-components/lib/esm/mui"
16
+ import {
17
+ LoadingLinear,
18
+ Resolver,
19
+ } from "@tellescope/react-components/lib/esm/loading"
20
+ import {
21
+ useSession,
22
+ useEnduserSession,
23
+ } from "@tellescope/react-components/lib/esm/authentication"
24
+ import {
25
+ useChatRooms,
26
+ useChats,
27
+ } from "@tellescope/react-components/lib/esm/state"
28
+ import {
29
+ useEndusers,
30
+ } from "@tellescope/react-components/lib/esm/user_state"
31
+ import {
32
+ useUserDisplayNames,
33
+ } from "@tellescope/react-components/lib/esm/enduser_state"
34
+
35
+ import {
36
+ ChatRoom,
37
+ ChatMessage,
38
+ } from "@tellescope/types-client"
39
+
40
+ import {
41
+ LoadedData,
42
+ LoadingStatus,
43
+ SessionType,
44
+ } from "@tellescope/types-utilities"
45
+
46
+ import {
47
+ user_display_name,
48
+ } from "@tellescope/utilities"
49
+
50
+ import {
51
+ PRIMARY_HEX,
52
+ } from "@tellescope/constants"
53
+
54
+ import {
55
+ Session,
56
+ EnduserSession,
57
+ } from "@tellescope/sdk"
58
+
59
+ const defaultMessagesStyle: CSSProperties = {
60
+ borderRadius: 5,
61
+ }
62
+ const baseMessageStyle = {
63
+ borderRadius: 25,
64
+ paddingRight: 10,
65
+ paddingLeft: 10,
66
+ margin: 5,
67
+ maxWidth: '80%',
68
+ }
69
+ const defaultSentStyle: CSSProperties = {
70
+ ...baseMessageStyle,
71
+ justifyContent: 'flex-end',
72
+ marginLeft: 'auto',
73
+ backgroundColor: PRIMARY_HEX,
74
+ }
75
+ const defaultReceivedStyle: CSSProperties = {
76
+ ...baseMessageStyle,
77
+ justifyContent: 'flex-start',
78
+ marginRight: 'auto',
79
+ backgroundColor: "#444444",
80
+ }
81
+ const baseTextStyle = {
82
+ color: "#ffffff",
83
+ padding: 4,
84
+ }
85
+ const defaultTextSentStyle: CSSProperties = {
86
+ ...baseTextStyle,
87
+ textAlign: 'right',
88
+ }
89
+ const defaultTextReceivedStyle: CSSProperties = {
90
+ ...baseTextStyle,
91
+ textAlign: 'left',
92
+ }
93
+
94
+ interface Messages_T {
95
+ messages: LoadedData<ChatMessage[]>,
96
+ chatUserId: string,
97
+ receivedMessageStyle?: CSSProperties,
98
+ receivedMessageTextStyle?: CSSProperties,
99
+ sentMessageStyle?: CSSProperties,
100
+ sentMessageTextStyle?: CSSProperties,
101
+ }
102
+ export const Messages = ({
103
+ messages,
104
+ chatUserId,
105
+ style=defaultMessagesStyle,
106
+ receivedMessageStyle=defaultReceivedStyle,
107
+ receivedMessageTextStyle=defaultTextReceivedStyle,
108
+ sentMessageStyle=defaultSentStyle,
109
+ sentMessageTextStyle=defaultTextSentStyle,
110
+ }: Messages_T & Styled) => (
111
+ <LoadingLinear data={messages} render={messages => (
112
+ <List reverse style={style} items={messages} render={(message) => (
113
+ <Flex key={message.id} style={message.senderId === chatUserId ? sentMessageStyle : receivedMessageStyle}>
114
+ <Typography style={message.senderId === chatUserId ? sentMessageTextStyle : receivedMessageTextStyle}>
115
+ {message.message}
116
+ </Typography>
117
+ </Flex>
118
+ )}/>
119
+ )}/>
120
+ )
121
+
122
+
123
+ const defaultSidebarStyle: CSSProperties = {
124
+ backgroundColor: "#858585",
125
+ borderRadius: 5,
126
+ overflowY: 'auto',
127
+ }
128
+ const defaultSidebarItemStyle: CSSProperties = {
129
+ backgroundColor: "#454545",
130
+ color: "#ffffff",
131
+ borderRadius: 5,
132
+ cursor: 'pointer',
133
+ maxHeight: 60,
134
+ justifyContent: 'center',
135
+ }
136
+ const defaultSidebarItemStyleSelected = {
137
+ ...defaultSidebarItemStyle,
138
+ backgroundColor: PRIMARY_HEX,
139
+ cursor: "default",
140
+ }
141
+ const defaultMessageNameStyle: CSSProperties = {
142
+ textAlign: 'right',
143
+ }
144
+ const defaultMessagePreviewStyle: CSSProperties = {
145
+ textAlign: 'right',
146
+ }
147
+
148
+ interface SidebarInfo {
149
+ selectedRoom?: string;
150
+ onRoomSelect: (roomId: string) => void;
151
+ style?: CSSProperties;
152
+ selectedItemStyle?: CSSProperties;
153
+ itemStyle?: CSSProperties;
154
+ nameStyle?: CSSProperties;
155
+ previewStyle?: CSSProperties;
156
+ }
157
+
158
+ interface Sidebar_T extends SidebarInfo {
159
+ resolveChatName: (r: ChatRoom) => string;
160
+ rooms: LoadedData<ChatRoom[]>;
161
+ }
162
+ export const Conversations = ({ rooms, selectedRoom, onRoomSelect, resolveChatName, style, selectedItemStyle, itemStyle, nameStyle, previewStyle } : Sidebar_T) => (
163
+ <LoadingLinear data={rooms} render={rooms =>
164
+ <List style={style ?? defaultSidebarStyle} items={rooms} onClick={onRoomSelect} render={(room, { onClick, index }) =>
165
+ <Flex key={room.id} flex={1} column onClick={() => selectedRoom !== room.id && onClick?.(room.id ?? index)}
166
+ style={selectedRoom === room.id ? (selectedItemStyle ?? defaultSidebarItemStyleSelected) : (itemStyle ?? defaultSidebarItemStyle) }
167
+ >
168
+ <Typography style={nameStyle ?? defaultMessageNameStyle}>
169
+ <Resolver item={room} resolver={resolveChatName}/>
170
+ </Typography>
171
+
172
+ <Typography style={previewStyle ?? defaultMessagePreviewStyle}>
173
+ {room.recentMessage}
174
+ </Typography>
175
+ </Flex>
176
+ }/>
177
+ }/>
178
+ )
179
+
180
+
181
+ export const EndusersConversations = ({ enduserId, ...p } : SidebarInfo & { enduserId: string }) => {
182
+ const [rooms] = useChatRooms('enduser')
183
+ const [displayNames] = useUserDisplayNames()
184
+
185
+ const resolveChatName = useCallback((r: ChatRoom) => {
186
+ if (r.title) return r.title
187
+
188
+ if (displayNames.status === LoadingStatus.Loaded) {
189
+ const user = displayNames.value.find(u => u.id === r.userIds?.[0])
190
+ if (user) return user_display_name(user)
191
+ }
192
+ return ''
193
+ }, [displayNames])
194
+
195
+ return <Conversations {...p} rooms={rooms} resolveChatName={resolveChatName}/>
196
+
197
+ }
198
+
199
+ export const UsersConversations = ({ userId, ...p } : SidebarInfo & { userId: string }) => {
200
+ const [rooms] = useChatRooms('user')
201
+ const [endusers] = useEndusers()
202
+
203
+ const resolveChatName = useCallback((r: ChatRoom) => {
204
+ if (r.title) return r.title
205
+
206
+ if (endusers.status === LoadingStatus.Loaded) {
207
+ const enduser = endusers.value.find(e => e.id === r.enduserIds?.[0])
208
+ if (enduser) return user_display_name(enduser)
209
+ }
210
+
211
+ return ''
212
+ }, [endusers])
213
+
214
+ return <Conversations {...p} rooms={rooms} resolveChatName={resolveChatName}/>
215
+ }
216
+
217
+ interface SendMessage_T {
218
+ session: Session | EnduserSession,
219
+ roomId: string,
220
+ onNewMessage: (m: ChatMessage) => void;
221
+ Icon?: React.ElementType<any>;
222
+ }
223
+ export const SendMessage = ({ session, roomId, Icon=SendIcon, onNewMessage }: SendMessage_T) => {
224
+ const [message, setMessage] = useState('')
225
+ const [sending, setSending] = useState(false)
226
+
227
+ return (
228
+ <Flex row flex={1} alignContent="center">
229
+ <Flex column flex={1}>
230
+ <TextField variant="outlined" value={message} onChange={setMessage} disabled={sending}
231
+ aria-label="Enter a message" placeholder="Enter a message" size="small"
232
+ />
233
+ </Flex>
234
+ <Flex column alignSelf="center">
235
+ <AsyncIconButton label="send" Icon={Icon} disabled={message === ''}
236
+ action={() => session.api.chats.createOne({ message, roomId })}
237
+ onSuccess={m => {
238
+ setMessage('')
239
+ onNewMessage(m)
240
+ }}
241
+ onChange={setSending}
242
+ />
243
+ </Flex>
244
+ </Flex>
245
+ )
246
+ }
247
+
248
+ const defaultSplitChatStyle: CSSProperties = {}
249
+ interface SplitChat_T {
250
+ session: EnduserSession | Session,
251
+ type: SessionType,
252
+ }
253
+ export const SplitChat = ({ session, type, style=defaultSplitChatStyle } : SplitChat_T & Styled) => {
254
+ const [, { updateElement: updateRoom }] = useChatRooms(type)
255
+ const [selectedRoom, setSelectedRoom] = useState('')
256
+ const [messages, { addElementForKey: addMessage }] = useChats(selectedRoom, type)
257
+
258
+ return (
259
+ <Flex row style={style} flex={1}>
260
+ <Flex column flex={1}>
261
+ {type === 'user'
262
+ ? <UsersConversations userId={session.userInfo.id} selectedRoom={selectedRoom} onRoomSelect={setSelectedRoom}/>
263
+ : <EndusersConversations selectedRoom={selectedRoom} enduserId={session.userInfo.id} onRoomSelect={setSelectedRoom}/>
264
+ }
265
+ </Flex>
266
+
267
+ <Flex column flex={2} style={{ backgroundColor: '#cccccc', borderRadius: 5 }}>
268
+ {selectedRoom &&
269
+ <>
270
+ <Flex row flex={8}>
271
+ <Messages messages={messages} chatUserId={session.userInfo.id}/>
272
+ </Flex>
273
+
274
+ <Flex row flex={1} style={{ marginLeft: 10, marginRight: 10 }}>
275
+ <SendMessage session={session} roomId={selectedRoom}
276
+ onNewMessage={m => {
277
+ addMessage(selectedRoom, m)
278
+ updateRoom(selectedRoom, { recentMessage: m.message, recentSender: m.senderId ?? '' })
279
+ }}
280
+ />
281
+ </Flex>
282
+ </>
283
+ }
284
+ </Flex>
285
+ </Flex>
286
+ )
287
+ }
288
+
289
+ export const UserChatSplit = ({ style=defaultSplitChatStyle } : Styled) => {
290
+ const session = useSession()
291
+ return (
292
+ <SplitChat session={session} type="user" style={style}/>
293
+ )
294
+ }
295
+
296
+ export const EnduserChatSplit = ({ style=defaultSplitChatStyle } : Styled) => {
297
+ const session = useEnduserSession()
298
+ return (
299
+ <SplitChat session={session} type="enduser" style={style}/>
300
+ )
301
+ }
@@ -0,0 +1 @@
1
+ export * from "./chat"
package/src/index.ts CHANGED
@@ -1,6 +1 @@
1
- import '@fontsource/roboto/300.css';
2
- import '@fontsource/roboto/400.css';
3
- import '@fontsource/roboto/500.css';
4
- import '@fontsource/roboto/700.css';
5
-
6
- export * from "./chat.web";
1
+ export * from "./chat";
package/tsconfig.json CHANGED
@@ -5,5 +5,8 @@
5
5
  "rootDir": "src",
6
6
  },
7
7
  "exclude": ["node_modules", "lib", "tests"],
8
- "include": ["src"]
8
+ "include": ["src"],
9
+ "references": [
10
+ { "path": "../components" },
11
+ ]
9
12
  }
@@ -1,4 +0,0 @@
1
- /// <reference types="react" />
2
- export declare const ChatsFromEndusersSidebar: () => JSX.Element;
3
- export declare const ChatsFromUsersSidebar: () => JSX.Element;
4
- //# sourceMappingURL=chat.web.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"chat.web.d.ts","sourceRoot":"","sources":["../../src/chat.web.tsx"],"names":[],"mappings":";AAiCA,eAAO,MAAM,wBAAwB,mBAKpC,CAAA;AAED,eAAO,MAAM,qBAAqB,mBAKjC,CAAA"}
@@ -1,25 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ChatsFromUsersSidebar = exports.ChatsFromEndusersSidebar = void 0;
4
- var jsx_runtime_1 = require("react/jsx-runtime");
5
- var react_components_1 = require("@tellescope/react-components");
6
- var authentication_1 = require("@tellescope/authentication");
7
- var Sidebar = function (_a) {
8
- var rooms = _a.rooms;
9
- return ((0, jsx_runtime_1.jsx)(react_components_1.LoadingLinear, { data: rooms, render: function (rooms) {
10
- return (0, jsx_runtime_1.jsx)(react_components_1.List, { items: rooms }, void 0);
11
- } }, void 0));
12
- };
13
- var ChatsFromEndusersSidebar = function () {
14
- var session = (0, authentication_1.useSession)();
15
- var _a = (0, react_components_1.useLoadedState)(function () { return session.api.chat_rooms.getSome(); }), rooms = _a[0], setRooms = _a[1];
16
- return (0, jsx_runtime_1.jsx)(Sidebar, { rooms: rooms }, void 0);
17
- };
18
- exports.ChatsFromEndusersSidebar = ChatsFromEndusersSidebar;
19
- var ChatsFromUsersSidebar = function () {
20
- var session = (0, authentication_1.useEnduserSession)();
21
- var _a = (0, react_components_1.useLoadedState)(), rooms = _a[0], setRooms = _a[1];
22
- return (0, jsx_runtime_1.jsx)(Sidebar, { rooms: rooms }, void 0);
23
- };
24
- exports.ChatsFromUsersSidebar = ChatsFromUsersSidebar;
25
- //# sourceMappingURL=chat.web.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"chat.web.js","sourceRoot":"","sources":["../../src/chat.web.tsx"],"names":[],"mappings":";;;;AAIA,iEAIqC;AAErC,6DAGmC;AAcnC,IAAM,OAAO,GAAG,UAAC,EAAoB;QAAlB,KAAK,WAAA;IAAkB,OAAA,CACxC,uBAAC,gCAAa,IAAC,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,UAAA,KAAK;YACvC,OAAO,uBAAC,uBAAI,IAAC,KAAK,EAAE,KAAK,WAAG,CAAA;QAC9B,CAAC,WAAG,CACL;AAJyC,CAIzC,CAAA;AAEM,IAAM,wBAAwB,GAAG;IACtC,IAAM,OAAO,GAAG,IAAA,2BAAU,GAAE,CAAA;IACtB,IAAA,KAAoB,IAAA,iCAAc,EAAC,cAAM,OAAA,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,OAAO,EAAE,EAAhC,CAAgC,CAAC,EAAzE,KAAK,QAAA,EAAE,QAAQ,QAA0D,CAAA;IAEhF,OAAO,uBAAC,OAAO,IAAC,KAAK,EAAE,KAAK,WAAG,CAAA;AACjC,CAAC,CAAA;AALY,QAAA,wBAAwB,4BAKpC;AAEM,IAAM,qBAAqB,GAAG;IACnC,IAAM,OAAO,GAAG,IAAA,kCAAiB,GAAE,CAAA;IAC7B,IAAA,KAAoB,IAAA,iCAAc,GAAc,EAA/C,KAAK,QAAA,EAAE,QAAQ,QAAgC,CAAA;IAEtD,OAAO,uBAAC,OAAO,IAAC,KAAK,EAAE,KAAK,WAAG,CAAA;AACjC,CAAC,CAAA;AALY,QAAA,qBAAqB,yBAKjC"}
@@ -1,3 +0,0 @@
1
- export declare const ChatsFromEndusersSidebar: () => JSX.Element;
2
- export declare const ChatsFromUsersSidebar: () => JSX.Element;
3
- //# sourceMappingURL=chat.web.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"chat.web.d.ts","sourceRoot":"","sources":["../../src/chat.web.tsx"],"names":[],"mappings":"AAiCA,eAAO,MAAM,wBAAwB,mBAKpC,CAAA;AAED,eAAO,MAAM,qBAAqB,mBAKjC,CAAA"}
@@ -1,20 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { List, LoadingLinear, useLoadedState, } from "@tellescope/react-components";
3
- import { useSession, useEnduserSession, } from "@tellescope/authentication";
4
- var Sidebar = function (_a) {
5
- var rooms = _a.rooms;
6
- return (_jsx(LoadingLinear, { data: rooms, render: function (rooms) {
7
- return _jsx(List, { items: rooms }, void 0);
8
- } }, void 0));
9
- };
10
- export var ChatsFromEndusersSidebar = function () {
11
- var session = useSession();
12
- var _a = useLoadedState(function () { return session.api.chat_rooms.getSome(); }), rooms = _a[0], setRooms = _a[1];
13
- return _jsx(Sidebar, { rooms: rooms }, void 0);
14
- };
15
- export var ChatsFromUsersSidebar = function () {
16
- var session = useEnduserSession();
17
- var _a = useLoadedState(), rooms = _a[0], setRooms = _a[1];
18
- return _jsx(Sidebar, { rooms: rooms }, void 0);
19
- };
20
- //# sourceMappingURL=chat.web.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"chat.web.js","sourceRoot":"","sources":["../../src/chat.web.tsx"],"names":[],"mappings":";AAIA,OAAO,EACL,IAAI,EACJ,aAAa,EACb,cAAc,GACf,MAAM,8BAA8B,CAAA;AAErC,OAAO,EACL,UAAU,EACV,iBAAiB,GAClB,MAAM,4BAA4B,CAAA;AAcnC,IAAM,OAAO,GAAG,UAAC,EAAoB;QAAlB,KAAK,WAAA;IAAkB,OAAA,CACxC,KAAC,aAAa,IAAC,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,UAAA,KAAK;YACvC,OAAO,KAAC,IAAI,IAAC,KAAK,EAAE,KAAK,WAAG,CAAA;QAC9B,CAAC,WAAG,CACL;AAJyC,CAIzC,CAAA;AAED,MAAM,CAAC,IAAM,wBAAwB,GAAG;IACtC,IAAM,OAAO,GAAG,UAAU,EAAE,CAAA;IACtB,IAAA,KAAoB,cAAc,CAAC,cAAM,OAAA,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,OAAO,EAAE,EAAhC,CAAgC,CAAC,EAAzE,KAAK,QAAA,EAAE,QAAQ,QAA0D,CAAA;IAEhF,OAAO,KAAC,OAAO,IAAC,KAAK,EAAE,KAAK,WAAG,CAAA;AACjC,CAAC,CAAA;AAED,MAAM,CAAC,IAAM,qBAAqB,GAAG;IACnC,IAAM,OAAO,GAAG,iBAAiB,EAAE,CAAA;IAC7B,IAAA,KAAoB,cAAc,EAAc,EAA/C,KAAK,QAAA,EAAE,QAAQ,QAAgC,CAAA;IAEtD,OAAO,KAAC,OAAO,IAAC,KAAK,EAAE,KAAK,WAAG,CAAA;AACjC,CAAC,CAAA"}
package/src/chat.web.tsx DELETED
@@ -1,46 +0,0 @@
1
- import React, { HTMLInputTypeAttribute, CSSProperties } from "react"
2
-
3
- import LinearProgress from '@mui/material/LinearProgress';
4
-
5
- import {
6
- List,
7
- LoadingLinear,
8
- useLoadedState,
9
- } from "@tellescope/react-components"
10
-
11
- import {
12
- useSession,
13
- useEnduserSession,
14
- } from "@tellescope/authentication"
15
-
16
- import {
17
- ChatRoom,
18
- ChatMessage,
19
- } from "@tellescope/types-client"
20
-
21
- import {
22
- LoadedData,
23
- } from "@tellescope/types-utilities"
24
-
25
- interface Sidebar_T {
26
- rooms: LoadedData<ChatRoom[]>,
27
- }
28
- const Sidebar = ({ rooms }: Sidebar_T) => (
29
- <LoadingLinear data={rooms} render={rooms => {
30
- return <List items={rooms}/>
31
- }}/>
32
- )
33
-
34
- export const ChatsFromEndusersSidebar = () => {
35
- const session = useSession()
36
- const [rooms, setRooms] = useLoadedState(() => session.api.chat_rooms.getSome())
37
-
38
- return <Sidebar rooms={rooms}/>
39
- }
40
-
41
- export const ChatsFromUsersSidebar = () => {
42
- const session = useEnduserSession()
43
- const [rooms, setRooms] = useLoadedState<ChatRoom[]>()
44
-
45
- return <Sidebar rooms={rooms}/>
46
- }