@webinex/chatify 1.0.0-alpha00 → 1.0.0-alpha01
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/cjs/index.js +1 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/types/ui/AddChatButton.d.ts +2 -0
- package/dist/cjs/types/ui/Avatar.d.ts +6 -0
- package/dist/cjs/types/ui/ChatHeaderMembers.d.ts +5 -0
- package/dist/cjs/types/ui/ChatHeaderSettingsButton.d.ts +5 -0
- package/dist/cjs/types/ui/Chatify.d.ts +17 -2
- package/dist/cjs/types/ui/Footer.d.ts +2 -0
- package/dist/cjs/types/ui/Header.d.ts +2 -0
- package/dist/cjs/types/ui/index.d.ts +5 -0
- package/dist/cjs/types/util/customize.d.ts +12 -0
- package/dist/cjs/types/util/index.d.ts +1 -0
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/types/ui/AddChatButton.d.ts +2 -0
- package/dist/esm/types/ui/Avatar.d.ts +6 -0
- package/dist/esm/types/ui/ChatHeaderMembers.d.ts +5 -0
- package/dist/esm/types/ui/ChatHeaderSettingsButton.d.ts +5 -0
- package/dist/esm/types/ui/Chatify.d.ts +17 -2
- package/dist/esm/types/ui/Footer.d.ts +2 -0
- package/dist/esm/types/ui/Header.d.ts +2 -0
- package/dist/esm/types/ui/index.d.ts +5 -0
- package/dist/esm/types/util/customize.d.ts +12 -0
- package/dist/esm/types/util/index.d.ts +1 -0
- package/dist/index.d.ts +48 -8
- package/package.json +1 -1
- package/src/ui/AddChatButton.tsx +19 -0
- package/src/ui/Aside.tsx +3 -2
- package/src/ui/Avatar.tsx +18 -0
- package/src/ui/ChatHeader.tsx +6 -22
- package/src/ui/ChatHeaderMembers.tsx +30 -0
- package/src/ui/ChatHeaderSettingsButton.tsx +26 -0
- package/src/ui/Chatify.tsx +31 -15
- package/src/ui/Footer.tsx +7 -0
- package/src/ui/Header.tsx +14 -0
- package/src/ui/MessageMd.tsx +2 -2
- package/src/ui/index.ts +5 -0
- package/src/util/customize.tsx +45 -0
- package/src/util/index.ts +1 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { FC } from 'react';
|
|
2
|
+
import { Account } from '../core';
|
|
3
|
+
import { Avatar as AntdAvatar } from 'antd';
|
|
4
|
+
import { customize } from '../util';
|
|
5
|
+
|
|
6
|
+
export interface AvatarProps {
|
|
7
|
+
account: Account;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const _Avatar: FC<AvatarProps> = (props: AvatarProps) => {
|
|
11
|
+
const { account } = props;
|
|
12
|
+
|
|
13
|
+
return <AntdAvatar src={account.avatar} />;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
_Avatar.displayName = 'Avatar';
|
|
17
|
+
|
|
18
|
+
export const Avatar = customize('Avatar', _Avatar);
|
package/src/ui/ChatHeader.tsx
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { useChat, useSelect, ChatListItem
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import { useChat, useSelect, ChatListItem } from '../core';
|
|
2
|
+
import { Col, Row, Space } from 'antd';
|
|
3
|
+
import { ChatHeaderMembers } from './ChatHeaderMembers';
|
|
4
|
+
import { ChatSettingsButton } from './ChatHeaderSettingsButton';
|
|
5
5
|
|
|
6
6
|
export interface ChatHeaderProps {
|
|
7
7
|
id: string;
|
|
@@ -15,30 +15,14 @@ export function ChatHeader(props: ChatHeaderProps) {
|
|
|
15
15
|
[id],
|
|
16
16
|
);
|
|
17
17
|
|
|
18
|
-
const dispatch = useDispatch();
|
|
19
|
-
const onSettingsClick = useCallback(
|
|
20
|
-
() => dispatch({ type: 'chat_settings_open', data: { chatId: id } }),
|
|
21
|
-
|
|
22
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
23
|
-
[dispatch],
|
|
24
|
-
);
|
|
25
|
-
|
|
26
18
|
return (
|
|
27
19
|
<div className="wxchtf-chat-header">
|
|
28
20
|
<Row justify="space-between" align="middle">
|
|
29
21
|
<Col className="wxchtf-chat-name">{chat?.name ?? chatListItem?.name}</Col>
|
|
30
22
|
<Col className="wxchtf-chat-members">
|
|
31
23
|
<Space align="center">
|
|
32
|
-
{
|
|
33
|
-
|
|
34
|
-
{chat.members.map((x) => (
|
|
35
|
-
<Tooltip key={x.id} title={x.name}>
|
|
36
|
-
<Avatar src={x.avatar}>{x.name}</Avatar>
|
|
37
|
-
</Tooltip>
|
|
38
|
-
))}
|
|
39
|
-
</Avatar.Group>
|
|
40
|
-
)}
|
|
41
|
-
<Button onClick={onSettingsClick} type="link" icon={<SettingOutlined />} />
|
|
24
|
+
<ChatHeaderMembers id={id} />
|
|
25
|
+
<ChatSettingsButton id={id} />
|
|
42
26
|
</Space>
|
|
43
27
|
</Col>
|
|
44
28
|
</Row>
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { FC } from 'react';
|
|
2
|
+
import { useChat } from '../core';
|
|
3
|
+
import { Avatar, Tooltip } from 'antd';
|
|
4
|
+
import { customize } from '../util';
|
|
5
|
+
|
|
6
|
+
export interface ChatHeaderMembersProps {
|
|
7
|
+
id: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const _ChatHeaderMembers: FC<ChatHeaderMembersProps> = (props) => {
|
|
11
|
+
const { id } = props;
|
|
12
|
+
const { data: chat } = useChat({ chatId: id });
|
|
13
|
+
|
|
14
|
+
if (!chat?.members) {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<Avatar.Group maxCount={5}>
|
|
20
|
+
{chat.members.map((x) => (
|
|
21
|
+
<Tooltip key={x.id} title={x.name}>
|
|
22
|
+
<Avatar src={x.avatar}>{x.name}</Avatar>
|
|
23
|
+
</Tooltip>
|
|
24
|
+
))}
|
|
25
|
+
</Avatar.Group>
|
|
26
|
+
);
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
_ChatHeaderMembers.displayName = 'ChatHeaderMembers';
|
|
30
|
+
export const ChatHeaderMembers = customize('ChatHeaderMembers', _ChatHeaderMembers);
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { useDispatch } from '../core';
|
|
2
|
+
import { Button } from 'antd';
|
|
3
|
+
import { SettingOutlined } from '@ant-design/icons';
|
|
4
|
+
import { FC, useCallback } from 'react';
|
|
5
|
+
import { customize } from '../util';
|
|
6
|
+
|
|
7
|
+
export interface ChatSettingsButtonProps {
|
|
8
|
+
id: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const _ChatSettingsButton: FC<ChatSettingsButtonProps> = (props) => {
|
|
12
|
+
const { id } = props;
|
|
13
|
+
const dispatch = useDispatch();
|
|
14
|
+
const onSettingsClick = useCallback(
|
|
15
|
+
() => dispatch({ type: 'chat_settings_open', data: { chatId: id } }),
|
|
16
|
+
|
|
17
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
18
|
+
[dispatch],
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
return <Button onClick={onSettingsClick} type="link" icon={<SettingOutlined />} />;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
_ChatSettingsButton.displayName = 'ChatSettingsButton';
|
|
25
|
+
|
|
26
|
+
export const ChatSettingsButton = customize('ChatSettingsButton', _ChatSettingsButton);
|
package/src/ui/Chatify.tsx
CHANGED
|
@@ -1,47 +1,63 @@
|
|
|
1
|
-
import { CSSProperties,
|
|
2
|
-
import { useSignalR, ReducerProvider,
|
|
1
|
+
import { CSSProperties, FC } from 'react';
|
|
2
|
+
import { useSignalR, ReducerProvider, useReadMonitor } from '../core';
|
|
3
3
|
import { Aside } from './Aside';
|
|
4
4
|
import { Main } from './Main';
|
|
5
|
-
import { Button } from 'antd';
|
|
6
5
|
import { Localizer, LocalizerContext, defaultLocalizer } from './localizer';
|
|
6
|
+
import { Avatar } from './Avatar';
|
|
7
|
+
import { CustomizeProvider } from '../util';
|
|
8
|
+
import { ChatHeaderMembers } from './ChatHeaderMembers';
|
|
9
|
+
import { ChatSettingsButton } from './ChatHeaderSettingsButton';
|
|
10
|
+
import { Header } from './Header';
|
|
11
|
+
import { AddChatButton } from './AddChatButton';
|
|
12
|
+
import { Footer } from './Footer';
|
|
13
|
+
|
|
14
|
+
export interface ChatifyCustomizeValue {
|
|
15
|
+
Avatar?: typeof Avatar.Component | null;
|
|
16
|
+
Header?: typeof Header.Component | null;
|
|
17
|
+
Footer?: typeof Footer.Component | null;
|
|
18
|
+
AddChatButton?: typeof AddChatButton.Component | null;
|
|
19
|
+
ChatHeaderMembers?: typeof ChatHeaderMembers.Component | null;
|
|
20
|
+
ChatSettingsButton?: typeof ChatSettingsButton.Component | null;
|
|
21
|
+
}
|
|
7
22
|
|
|
8
23
|
export interface ChatifyProps {
|
|
9
24
|
className?: string;
|
|
10
25
|
style?: CSSProperties;
|
|
11
26
|
localizer?: Localizer;
|
|
27
|
+
customize?: ChatifyCustomizeValue;
|
|
12
28
|
}
|
|
13
29
|
|
|
14
30
|
function Content(props: Pick<ChatifyProps, 'className' | 'style'>) {
|
|
15
31
|
const { className = '', style } = props;
|
|
16
32
|
useSignalR();
|
|
17
33
|
useReadMonitor();
|
|
18
|
-
const dispatch = useDispatch();
|
|
19
|
-
const onAddChat = useCallback(() => dispatch({ type: 'new_chat_open', data: undefined }), [dispatch]);
|
|
20
34
|
|
|
21
35
|
return (
|
|
22
36
|
<div className={className + ' wxchtf-chatify'} style={style}>
|
|
23
|
-
<
|
|
24
|
-
<Button onClick={onAddChat} icon={'+'} type="link">
|
|
25
|
-
Add chat
|
|
26
|
-
</Button>
|
|
27
|
-
</div>
|
|
37
|
+
<Header />
|
|
28
38
|
<div className="wxchtf-body">
|
|
29
39
|
<Aside />
|
|
30
40
|
<Main />
|
|
31
41
|
</div>
|
|
32
|
-
<
|
|
42
|
+
<Footer />
|
|
33
43
|
</div>
|
|
34
44
|
);
|
|
35
45
|
}
|
|
36
46
|
|
|
37
|
-
|
|
38
|
-
|
|
47
|
+
const EMPTY_CUSTOMIZE = {};
|
|
48
|
+
|
|
49
|
+
export const Chatify: FC<ChatifyProps> = (props) => {
|
|
50
|
+
const { localizer = defaultLocalizer, customize = EMPTY_CUSTOMIZE } = props;
|
|
39
51
|
|
|
40
52
|
return (
|
|
41
53
|
<LocalizerContext.Provider value={localizer}>
|
|
42
54
|
<ReducerProvider>
|
|
43
|
-
<
|
|
55
|
+
<CustomizeProvider value={customize}>
|
|
56
|
+
<Content {...props} />
|
|
57
|
+
</CustomizeProvider>
|
|
44
58
|
</ReducerProvider>
|
|
45
59
|
</LocalizerContext.Provider>
|
|
46
60
|
);
|
|
47
|
-
}
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
Chatify.displayName = 'Chatify';
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { FC } from 'react';
|
|
2
|
+
import { AddChatButton } from './AddChatButton';
|
|
3
|
+
import { customize } from '../util';
|
|
4
|
+
|
|
5
|
+
const _Header: FC = () => {
|
|
6
|
+
return (
|
|
7
|
+
<div className="wxchtf-header">
|
|
8
|
+
<AddChatButton />
|
|
9
|
+
</div>
|
|
10
|
+
);
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
_Header.displayName = 'Header';
|
|
14
|
+
export const Header = customize('Header', _Header);
|
package/src/ui/MessageMd.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Avatar } from 'antd';
|
|
2
1
|
import { Account, File } from '../core';
|
|
2
|
+
import { Avatar } from './Avatar';
|
|
3
3
|
import { useLocalizer } from './localizer';
|
|
4
4
|
import React from 'react';
|
|
5
5
|
|
|
@@ -26,7 +26,7 @@ export const MessageMd = React.forwardRef(
|
|
|
26
26
|
>
|
|
27
27
|
{author && (
|
|
28
28
|
<div className="wxchtf-message-author">
|
|
29
|
-
<Avatar
|
|
29
|
+
<Avatar account={author} />
|
|
30
30
|
</div>
|
|
31
31
|
)}
|
|
32
32
|
<div className="wxchtf-message-body">
|
package/src/ui/index.ts
CHANGED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import React, { FC, PropsWithChildren, useContext } from 'react';
|
|
2
|
+
|
|
3
|
+
export type Customizable<TComponent extends React.ComponentType<any>, TKey extends string> = TComponent & {
|
|
4
|
+
Component: TComponent;
|
|
5
|
+
key: TKey;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
const CustomizeContext = React.createContext<CustomizeProviderValue>(null!);
|
|
9
|
+
|
|
10
|
+
export interface CustomizeProviderValue {
|
|
11
|
+
[key: string]: React.ComponentType<any> | null;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function CustomizeProvider(props: PropsWithChildren<{ value: CustomizeProviderValue }>) {
|
|
15
|
+
const { children, value } = props;
|
|
16
|
+
return <CustomizeContext.Provider value={value}>{children}</CustomizeContext.Provider>;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function useCustom<TComponent extends React.ComponentType>(key: string): TComponent | undefined | null {
|
|
20
|
+
const value = useContext(CustomizeContext);
|
|
21
|
+
return value[key] as TComponent | null | undefined;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function customize<TComponent extends React.ComponentType<any>, TKey extends string>(
|
|
25
|
+
key: TKey,
|
|
26
|
+
Component: TComponent,
|
|
27
|
+
): Customizable<TComponent, TKey> {
|
|
28
|
+
const Result: FC<any> = React.forwardRef<TComponent, any>((props: any, forwardRef) => {
|
|
29
|
+
const Custom = useCustom(key);
|
|
30
|
+
|
|
31
|
+
if (Custom === null) {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (Custom) {
|
|
36
|
+
return <Custom {...props} ref={forwardRef} />;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return <Component {...props} ref={forwardRef} />;
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
Result.displayName = 'Customizable.' + Component.displayName;
|
|
43
|
+
|
|
44
|
+
return Object.assign(Result, { key, Component }) as any;
|
|
45
|
+
}
|
package/src/util/index.ts
CHANGED