2018-12-07 04:59:25 +00:00
|
|
|
import React from 'react';
|
|
|
|
import PropTypes from 'prop-types';
|
|
|
|
import Toast from './toast';
|
|
|
|
|
|
|
|
const hasCustomId = settings => Object.hasOwnProperty.call(settings, 'id');
|
|
|
|
|
|
|
|
export default class ToastManager extends React.PureComponent {
|
|
|
|
static propTypes = {
|
2019-01-31 09:37:02 +00:00
|
|
|
/**
|
|
|
|
* Function called with the `this.notify` function.
|
|
|
|
*/
|
2018-12-07 04:59:25 +00:00
|
|
|
bindNotify: PropTypes.func.isRequired,
|
|
|
|
|
2019-01-31 09:37:02 +00:00
|
|
|
/**
|
|
|
|
* Function called with the `this.getToasts` function.
|
|
|
|
*/
|
2018-12-07 04:59:25 +00:00
|
|
|
bindGetToasts: PropTypes.func.isRequired,
|
|
|
|
|
2019-01-31 09:37:02 +00:00
|
|
|
/**
|
|
|
|
* Function called with the `this.closeAll` function.
|
|
|
|
*/
|
2018-12-07 04:59:25 +00:00
|
|
|
bindCloseAll: PropTypes.func.isRequired
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2018-12-07 04:59:25 +00:00
|
|
|
|
|
|
|
static idCounter = 0;
|
|
|
|
|
|
|
|
constructor(props, context) {
|
|
|
|
super(props, context);
|
|
|
|
|
|
|
|
props.bindNotify(this.notify);
|
|
|
|
props.bindGetToasts(this.getToasts);
|
|
|
|
props.bindCloseAll(this.closeAll);
|
|
|
|
|
|
|
|
this.state = {
|
|
|
|
toasts: []
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
getToasts = () => {
|
|
|
|
return this.state.toasts;
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2018-12-07 04:59:25 +00:00
|
|
|
|
|
|
|
closeAll = () => {
|
|
|
|
this.getToasts().forEach(toast => toast.close());
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2018-12-07 04:59:25 +00:00
|
|
|
|
|
|
|
notify = (title, settings) => {
|
2019-01-31 09:37:02 +00:00
|
|
|
// If there's a custom toast ID passed, close existing toasts with the same custom ID
|
2018-12-07 04:59:25 +00:00
|
|
|
if (hasCustomId(settings)) {
|
|
|
|
for (const toast of this.state.toasts) {
|
2019-01-31 09:37:02 +00:00
|
|
|
// Since unique ID is still appended to a custom ID, skip the unique ID and check only prefix
|
2018-12-07 04:59:25 +00:00
|
|
|
if (String(toast.id).startsWith(settings.id)) {
|
|
|
|
this.closeToast(toast.id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const instance = this.createToastInstance(title, settings);
|
|
|
|
|
|
|
|
this.setState(previousState => {
|
|
|
|
return {
|
|
|
|
toasts: [instance, ...previousState.toasts]
|
|
|
|
};
|
|
|
|
});
|
|
|
|
|
|
|
|
return instance;
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2018-12-07 04:59:25 +00:00
|
|
|
|
|
|
|
createToastInstance = (title, settings) => {
|
|
|
|
const uniqueId = ++ToastManager.idCounter;
|
|
|
|
const id = hasCustomId(settings) ? `${settings.id}-${uniqueId}` : uniqueId;
|
|
|
|
|
2024-06-25 08:46:29 +00:00
|
|
|
let hasCloseButton = settings.hasCloseButton || true;
|
|
|
|
let duration = settings.duration || 2;
|
|
|
|
if (settings.hasCloseButton !== undefined) {
|
|
|
|
hasCloseButton = settings.hasCloseButton;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (settings.duration !== undefined) {
|
|
|
|
duration = settings.duration;
|
|
|
|
}
|
|
|
|
|
2018-12-07 04:59:25 +00:00
|
|
|
return {
|
|
|
|
id,
|
|
|
|
title,
|
|
|
|
description: settings.description,
|
2024-06-25 08:46:29 +00:00
|
|
|
hasCloseButton: hasCloseButton,
|
|
|
|
duration: duration,
|
2018-12-07 04:59:25 +00:00
|
|
|
close: () => this.closeToast(id),
|
|
|
|
intent: settings.intent
|
|
|
|
};
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2018-12-07 04:59:25 +00:00
|
|
|
|
2019-01-31 09:37:02 +00:00
|
|
|
/**
|
|
|
|
* This will set isShown on the Toast which will close the toast.
|
|
|
|
* It won't remove the toast until onExited triggers onRemove.
|
|
|
|
*/
|
2018-12-07 04:59:25 +00:00
|
|
|
closeToast = id => {
|
|
|
|
this.setState(previousState => {
|
|
|
|
return {
|
|
|
|
toasts: previousState.toasts.map(toast => {
|
|
|
|
if (toast.id === id) {
|
|
|
|
return {
|
|
|
|
...toast,
|
|
|
|
isShown: false
|
|
|
|
};
|
|
|
|
}
|
|
|
|
return toast;
|
|
|
|
})
|
|
|
|
};
|
|
|
|
});
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2018-12-07 04:59:25 +00:00
|
|
|
|
|
|
|
removeToast = id => {
|
|
|
|
this.setState(previousState => {
|
|
|
|
return {
|
|
|
|
toasts: previousState.toasts.filter(toast => toast.id !== id)
|
|
|
|
};
|
|
|
|
});
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2018-12-07 04:59:25 +00:00
|
|
|
|
|
|
|
render() {
|
|
|
|
return (
|
2024-06-25 08:46:29 +00:00
|
|
|
<div className="seahub-toast-manager">
|
2018-12-07 04:59:25 +00:00
|
|
|
{this.state.toasts.map(({ id, description, ...props }) => {
|
|
|
|
return (
|
|
|
|
<Toast key={id} onRemove={() => this.removeToast(id)} {...props}>
|
|
|
|
{description}
|
|
|
|
</Toast>
|
|
|
|
);
|
|
|
|
})}
|
2024-06-25 08:46:29 +00:00
|
|
|
</div>
|
2018-12-07 04:59:25 +00:00
|
|
|
);
|
|
|
|
}
|
2023-09-13 00:40:50 +00:00
|
|
|
}
|