Skip to content

Commit

Permalink
feat: add MessageStatus
Browse files Browse the repository at this point in the history
  • Loading branch information
akai committed Jul 13, 2021
1 parent 2b8deed commit b145305
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 2 deletions.
9 changes: 7 additions & 2 deletions src/components/Message/Message.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from 'react';
import clsx from 'clsx';
import { SystemMessage } from './SystemMessage';
import { IMessageStatus } from '../MessageStatus';
import { Avatar } from '../Avatar';
import { Time } from '../Time';
import { Typing } from '../Typing';
Expand Down Expand Up @@ -42,6 +43,10 @@ export interface MessageProps {
* 是否显示时间
*/
hasTime?: boolean;
/**
* 状态
*/
status?: IMessageStatus;
/**
* 消息内容渲染函数
*/
Expand All @@ -50,14 +55,14 @@ export interface MessageProps {

const Message = (props: MessageProps) => {
const { renderMessageContent = () => null, ...msg } = props;
const { type, content, user } = msg;
const { type, content, user, _id: id } = msg;

if (type === 'system') {
return <SystemMessage content={content.text} action={content.action} />;
}

return (
<div className={clsx('Message', msg.position)} data-type={type} data-id={msg._id}>
<div className={clsx('Message', msg.position)} data-id={id} data-type={type}>
{msg.hasTime && msg.createdAt && (
<div className="Message-meta">
<Time date={msg.createdAt} />
Expand Down
77 changes: 77 additions & 0 deletions src/components/MessageStatus/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import React, { useState, useRef, useEffect, useCallback } from 'react';
import { Icon } from '../Icon';
import { IconButton } from '../IconButton';

export type IMessageStatus = 'pending' | 'sent' | 'fail';

export interface MessageStatusProps {
status: IMessageStatus;
delay?: number;
maxDelay?: number;
onRetry?: () => void;
}

export const MessageStatus = ({
status,
delay = 1500,
maxDelay = 5000,
onRetry,
}: MessageStatusProps) => {
const [type, setType] = useState('');
const loadingTimerRef = useRef<ReturnType<typeof setTimeout>>();
const failTimerRef = useRef<ReturnType<typeof setTimeout>>();

const doTimeout = useCallback(() => {
loadingTimerRef.current = setTimeout(() => {
setType('loading');
}, delay);

failTimerRef.current = setTimeout(() => {
setType('fail');
}, maxDelay);
}, [delay, maxDelay]);

function clear() {
if (loadingTimerRef.current) {
clearTimeout(loadingTimerRef.current);
}
if (failTimerRef.current) {
clearTimeout(failTimerRef.current);
}
}

useEffect(() => {
clear();
if (status === 'pending') {
doTimeout();
} else if (status === 'sent') {
setType('');
} else if (status === 'fail') {
setType('fail');
}

return clear;
}, [status, doTimeout]);

function handleRetry() {
setType('loading');
doTimeout();
if (onRetry) {
onRetry();
}
}

if (type) {
return (
<div className="MessageStatus" data-status={type}>
{type === 'fail' ? (
<IconButton icon="error-circle" onClick={handleRetry} />
) : (
<Icon type="spinner" spin onClick={handleRetry} />
)}
</div>
);
}

return null;
};
22 changes: 22 additions & 0 deletions src/components/MessageStatus/style.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
.MessageStatus {
align-self: center;
margin-right: @gutter;

&[data-status='loading'] {
.Icon {
color: var(--gray-4);
}
}
&[data-status='fail'] {
.IconBtn {
color: #ff5959;
}
}
.IconBtn,
.Icon {
display: block;
}
.Message.right .Bubble + & {
margin-right: (@gutter - @bubble-right-gutter);
}
}
2 changes: 2 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ export { MediaObject } from './components/MediaObject';
export type { MediaObjectProps } from './components/MediaObject';
export { Message, SystemMessage } from './components/Message';
export type { MessageProps, SystemMessageProps } from './components/Message';
export { MessageStatus } from './components/MessageStatus';
export type { MessageStatusProps } from './components/MessageStatus';
export { Modal, Confirm, Popup } from './components/Modal';
export type { ModalProps } from './components/Modal';
export { Navbar } from './components/Navbar';
Expand Down
1 change: 1 addition & 0 deletions src/styles/index.less
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
@import '../components/Loading/style';
@import '../components/MediaObject/style';
@import '../components/Message/style';
@import '../components/MessageStatus/style';
@import '../components/Modal/style';
@import '../components/Navbar/style';
@import '../components/Notice/style';
Expand Down

0 comments on commit b145305

Please sign in to comment.