import { message as antdMessage } from 'antd';
import PubSub from 'pubsub-js';
import { useEffect } from 'react';
export type NoticeType = 'info' | 'success' | 'error' | 'warning' | 'loading' | 'open' | 'destroy';
export interface ConfigOptions {
top?: number;
duration?: number;
prefixCls?: string;
getContainer?: () => HTMLElement;
transitionName?: string;
maxCount?: number;
rtl?: boolean;
}
export interface ArgsProps {
content: React.ReactNode;
duration?: number;
type?: NoticeType;
onClose?: () => void;
icon?: React.ReactNode;
key?: string | number;
style?: React.CSSProperties;
className?: string;
onClick?: (e: React.MouseEvent<HTMLDivElement>) => void;
}
export type JointContent = React.ReactNode | ArgsProps;
export interface MessageType extends PromiseLike<boolean> {
(): void;
}
export type TypeOpen = (
content: JointContent,
duration?: number | VoidFunction,
onClose?: VoidFunction,
) => void;
interface MessageMethods {
info: TypeOpen;
success: TypeOpen;
error: TypeOpen;
warning: TypeOpen;
loading: TypeOpen;
}
interface BaseMethods {
open(args: ArgsProps): MessageType;
destroy(key?: React.Key): void;
}
interface AntdMessageEventConfig {
messageType: NoticeType;
content: JointContent;
duration?: number | VoidFunction;
onClose?: VoidFunction;
key?: React.Key;
}
const isLegacyChrome = () => {
const ua = navigator.userAgent;
if (ua.indexOf('Chrome') === -1) {
return false;
}
const version = parseInt(ua.split('Chrome/')[1], 10);
return version < 89;
};
const ANTD_MESSAGE_EVENT = 'ANTD_MESSAGE_EVENT';
const messageAdapter = () => {
const message: Partial<MessageMethods & BaseMethods> = {};
const typeList: NoticeType[] = [
'info',
'success',
'error',
'warning',
'loading',
'open',
'destroy',
];
typeList.forEach((messageType) => {
if (['info', 'success', 'error', 'warning', 'loading'].includes(messageType)) {
message[messageType as 'info' | 'success' | 'error' | 'warning' | 'loading'] = (
content: JointContent,
duration?: number | VoidFunction,
onClose?: VoidFunction,
) => {
try {
PubSub.publish(ANTD_MESSAGE_EVENT, { messageType, content, duration, onClose });
} catch (e) {
console.error(e);
}
};
} else if (['open'].includes(messageType)) {
message[messageType as 'open'] = (args: ArgsProps): MessageType => {
let result = false;
try {
result = PubSub.publish(ANTD_MESSAGE_EVENT, { messageType, ...args });
} catch (e) {
console.error(e);
}
return Promise.resolve(result) as unknown as MessageType;
};
} else if (['destroy'].includes(messageType)) {
message[messageType as 'destroy'] = (key?: React.Key) => {
try {
PubSub.publish(ANTD_MESSAGE_EVENT, { messageType, key });
} catch (e) {
console.error(e);
}
};
}
});
return message as MessageMethods & BaseMethods;
};
const useMessageAdapter = () => {
const [messageApi, contextHolder] = antdMessage.useMessage();
useEffect(() => {
if (!isLegacyChrome()) return;
const token = PubSub.subscribe(
ANTD_MESSAGE_EVENT,
(eventName, config: AntdMessageEventConfig) => {
const { messageType, content, duration, onClose } = config;
if (['info', 'success', 'error', 'warning', 'loading'].includes(messageType)) {
(messageApi[messageType] as TypeOpen)(content, duration, onClose);
} else if (['open'].includes(messageType)) {
(messageApi[messageType] as (args: ArgsProps) => MessageType)(config as ArgsProps);
} else if (['destroy'].includes(messageType)) {
(messageApi[messageType] as (key?: React.Key) => void)(config.key);
}
},
);
return () => {
PubSub.unsubscribe(token);
};
}, []);
if (!isLegacyChrome()) {
return [null];
}
return [contextHolder];
};
const message = isLegacyChrome() ? messageAdapter() : antdMessage;
export { message, useMessageAdapter };