226 lines
6 KiB
JavaScript
226 lines
6 KiB
JavaScript
import { h, render, Component } from 'preact';
|
|
import PropTypes from 'prop-types';
|
|
import setupPusher from './pusher';
|
|
|
|
class UnopenedChannelNotice extends Component {
|
|
propTypes = {
|
|
pusherKey: PropTypes.Object,
|
|
};
|
|
|
|
static defaultProps = {
|
|
pusherKey: undefined,
|
|
};
|
|
|
|
constructor(props) {
|
|
super(props);
|
|
this.state = {
|
|
visible: false,
|
|
unopenedChannels: [],
|
|
};
|
|
}
|
|
|
|
componentDidMount() {
|
|
const { pusherKey } = this.props;
|
|
setupPusher(pusherKey, {
|
|
channelId: `private-message-notifications-${window.currentUser.id}`,
|
|
messageCreated: this.receiveNewMessage,
|
|
messageDeleted: this.removeMessage,
|
|
messageEdited: this.updateMessage,
|
|
mentioned: this.mentionedMessage,
|
|
messageOpened: this.messageOpened,
|
|
});
|
|
this.fetchUnopenedChannel(this.updateMessageNotification);
|
|
|
|
document.getElementById('connect-link').onclick = () => {
|
|
// Hack, should probably be its own component in future
|
|
document.getElementById('connect-number').classList.add('hidden');
|
|
this.setState({ visible: false });
|
|
};
|
|
}
|
|
|
|
updateMessageNotification = unopenedChannels => {
|
|
const number = document.getElementById('connect-number');
|
|
this.setState({ unopenedChannels });
|
|
if (unopenedChannels.length > 0) {
|
|
number.classList.remove('hidden');
|
|
number.innerHTML = unopenedChannels.length;
|
|
document.getElementById('connect-link').href = '/connect/' + unopenedChannels[0].adjusted_slug;
|
|
InstantClick.preload(
|
|
document.getElementById('connect-link').href,
|
|
'force',
|
|
);
|
|
} else {
|
|
number.classList.add('hidden');
|
|
}
|
|
};
|
|
|
|
removeMessage = () => {};
|
|
|
|
updateMessage = () => {};
|
|
|
|
mentionedMessage = e => {
|
|
if (window.location.pathname.startsWith('/connect')) {
|
|
return;
|
|
}
|
|
|
|
this.setState(prevState => ({
|
|
unopenedChannels: prevState.unopenedChannels.map(unopenedChannel =>
|
|
unopenedChannel.adjusted_slug === e.chat_channel_adjusted_slug
|
|
? { ...unopenedChannel, request_type: 'mentioned' }
|
|
: unopenedChannel,
|
|
),
|
|
visible: true,
|
|
}));
|
|
|
|
this.hideNotice();
|
|
};
|
|
|
|
messageOpened = e => {
|
|
const { unopenedChannels } = this.state;
|
|
if (
|
|
!window.location.pathname.startsWith('/connect') ||
|
|
!window.location.pathname.includes(e.adjusted_slug)
|
|
)
|
|
return;
|
|
this.updateMessageNotification(
|
|
unopenedChannels.filter(
|
|
unopenedChannel => unopenedChannel.adjusted_slug !== e.adjusted_slug,
|
|
),
|
|
);
|
|
};
|
|
|
|
receiveNewMessage = e => {
|
|
if (
|
|
(window.location.pathname.startsWith('/connect') &&
|
|
e.user_id === window.currentUser.id &&
|
|
e.channel_type !== 'direct') ||
|
|
window.location.pathname.includes(e.chat_channel_adjusted_slug)
|
|
) {
|
|
return;
|
|
}
|
|
const { unopenedChannels } = this.state;
|
|
const newObj = { adjusted_slug: e.chat_channel_adjusted_slug };
|
|
|
|
const ifMessageExist = unopenedChannels.some(
|
|
channel => channel.adjusted_slug === newObj.adjusted_slug,
|
|
);
|
|
|
|
if (
|
|
!ifMessageExist &&
|
|
newObj.adjusted_slug !== `@${window.currentUser.username}`
|
|
) {
|
|
unopenedChannels.push(newObj);
|
|
}
|
|
if (ifMessageExist) {
|
|
const index = unopenedChannels.findIndex(
|
|
channel => channel.adjusted_slug === newObj.adjusted_slug,
|
|
);
|
|
unopenedChannels[index].notified = false;
|
|
}
|
|
|
|
if (!window.location.pathname.startsWith('/connect')) {
|
|
this.setState({
|
|
visible:
|
|
unopenedChannels.length > 0 &&
|
|
e.user_id !== window.currentUser.id &&
|
|
e.channel_type === 'direct',
|
|
});
|
|
}
|
|
this.updateMessageNotification(unopenedChannels);
|
|
this.hideNotice();
|
|
};
|
|
|
|
handleClick = () => {
|
|
this.hideNotice();
|
|
};
|
|
|
|
hideNotice = () => {
|
|
setTimeout(() => {
|
|
this.setState(prevState => ({
|
|
unopenedChannels: prevState.unopenedChannels.map(unopenedChannel =>
|
|
!unopenedChannel.notified
|
|
? { ...unopenedChannel, notified: true }
|
|
: unopenedChannel,
|
|
),
|
|
visible: false,
|
|
}));
|
|
}, 7500);
|
|
};
|
|
|
|
fetchUnopenedChannel = successCb => {
|
|
fetch('/chat_channels?state=unopened', {
|
|
Accept: 'application/json',
|
|
'Content-Type': 'application/json',
|
|
credentials: 'same-origin',
|
|
})
|
|
.then(response => response.json())
|
|
.then(successCb);
|
|
};
|
|
|
|
render() {
|
|
const { visible, unopenedChannels } = this.state;
|
|
if (visible && unopenedChannels.some(channel => !channel.notified)) {
|
|
const message = unopenedChannels.map(channel => {
|
|
if (channel.notified) return null;
|
|
return (
|
|
<div>
|
|
{channel.request_type === 'mentioned'
|
|
? 'You got mentioned in'
|
|
: 'New Message from'}
|
|
{' '}
|
|
<a
|
|
href={`/connect/${channel.adjusted_slug}`}
|
|
style={{
|
|
background: '#66e2d5',
|
|
color: 'black',
|
|
border: '1px solid black',
|
|
padding: '2px 7px',
|
|
display: 'inline-block',
|
|
margin: '3px 6px',
|
|
borderRadius: '3px',
|
|
}}
|
|
>
|
|
{channel.adjusted_slug}
|
|
</a>
|
|
</div>
|
|
);
|
|
});
|
|
|
|
return (
|
|
<a
|
|
href={`/connect/${unopenedChannels[0].adjusted_slug}`}
|
|
onClick={this.handleClick}
|
|
style={{
|
|
position: 'fixed',
|
|
zIndex: '200',
|
|
top: '44px',
|
|
right: 0,
|
|
left: 0,
|
|
background: '#66e2d5',
|
|
borderBottom: '1px solid black',
|
|
color: 'black',
|
|
fontWeight: 'bold',
|
|
textAlign: 'center',
|
|
fontSize: '17px',
|
|
opacity: '0.94',
|
|
padding: '19px 5px 14px',
|
|
}}
|
|
>
|
|
{message}
|
|
</a>
|
|
);
|
|
}
|
|
|
|
return '';
|
|
}
|
|
}
|
|
|
|
export default function getUnopenedChannels() {
|
|
if (window.frameElement) {
|
|
return;
|
|
}
|
|
render(
|
|
<UnopenedChannelNotice pusherKey={document.body.dataset.pusherKey} />,
|
|
document.getElementById('message-notice'),
|
|
);
|
|
}
|