1
0
mirror of https://github.com/ascribe/onion.git synced 2024-06-28 00:28:00 +02:00

Implement pause and resume functionality to global notifications

Also part of this change:
* Handle the notification cooldown periods using status changes rather
than emptying the queue
* Refactor how notifications are rendered
This commit is contained in:
Brett Sun 2015-11-21 19:23:20 +01:00
parent 60bf4b12f5
commit 6649b7d7f1
3 changed files with 83 additions and 74 deletions

View File

@ -2,13 +2,15 @@
import { alt } from '../alt';
class GlobalNotificationActions {
constructor() {
this.generateActions(
'appendGlobalNotification',
'showNextGlobalNotification',
'shiftGlobalNotification',
'emulateEmptyStore'
'cooldownGlobalNotifications',
'pauseGlobalNotifications',
'resumeGlobalNotifications'
);
}
}

View File

@ -1,7 +1,9 @@
'use strict';
import React from 'react';
import classNames from 'classnames';
import GlobalNotificationActions from '../actions/global_notification_actions';
import GlobalNotificationStore from '../stores/global_notification_store';
import Row from 'react-bootstrap/lib/Row';
@ -9,14 +11,18 @@ import Col from 'react-bootstrap/lib/Col';
import { mergeOptions } from '../utils/general_utils';
const MAX_NOTIFICATION_BUBBLE_CONTAINER_WIDTH = 768;
let GlobalNotification = React.createClass({
getInitialState() {
const notificationStore = GlobalNotificationStore.getState();
return mergeOptions(
{
containerWidth: 0
},
this.extractFirstElem(GlobalNotificationStore.getState().notificationQue)
notificationStore
);
},
@ -36,35 +42,8 @@ let GlobalNotification = React.createClass({
window.removeEventListener('resize', this.handleContainerResize);
},
extractFirstElem(l) {
if(l.length > 0) {
return {
show: true,
message: l[0]
};
} else {
return {
show: false,
message: ''
};
}
},
onChange(state) {
let notification = this.extractFirstElem(state.notificationQue);
// error handling for notifications
if(notification.message && notification.type === 'danger') {
console.logGlobal(new Error(notification.message.message));
}
if(notification.show) {
this.setState(notification);
} else {
this.setState({
show: false
});
}
this.setState(state);
},
handleContainerResize() {
@ -73,32 +52,28 @@ let GlobalNotification = React.createClass({
});
},
render() {
let notificationClass = 'ascribe-global-notification';
let textClass;
renderNotification() {
const {
notificationQueue: [notification],
notificationStatus,
notificationsPaused,
containerWidth } = this.state;
if(this.state.containerWidth > 768) {
notificationClass = 'ascribe-global-notification-bubble';
if (notification && !notificationsPaused) {
const notificationClasses = [];
let textClass;
if(this.state.show) {
notificationClass += ' ascribe-global-notification-bubble-on';
if (this.state.containerWidth > 768) {
notificationClasses.push('ascribe-global-notification-bubble');
notificationClasses.push(notificationStatus === 'show' ? 'ascribe-global-notification-bubble-on'
: 'ascribe-global-notification-bubble-off');
} else {
notificationClass += ' ascribe-global-notification-bubble-off';
notificationClasses.push('ascribe-global-notification');
notificationClasses.push(notificationStatus === 'show' ? 'ascribe-global-notification-on'
: 'ascribe-global-notification-off');
}
} else {
notificationClass = 'ascribe-global-notification';
if(this.state.show) {
notificationClass += ' ascribe-global-notification-on';
} else {
notificationClass += ' ascribe-global-notification-off';
}
}
if(this.state.message) {
switch(this.state.message.type) {
switch(notification.type) {
case 'success':
textClass = 'ascribe-global-notification-success';
break;
@ -106,18 +81,23 @@ let GlobalNotification = React.createClass({
textClass = 'ascribe-global-notification-danger';
break;
default:
console.warn('Could not find a matching type in global_notification.js');
console.warn('Could not find a matching notification type in global_notification.js');
}
}
return (
<div className={classNames(...notificationClasses)}>
<div className={textClass}>{notification.message}</div>
</div>
);
}
},
render() {
return (
<div ref="notificationWrapper">
<Row>
<Col>
<div className={notificationClass}>
<div className={textClass}>{this.state.message.message}</div>
</div>
{this.renderNotification()}
</Col>
</Row>
</div>
@ -125,4 +105,4 @@ let GlobalNotification = React.createClass({
}
});
export default GlobalNotification;
export default GlobalNotification;

View File

@ -4,36 +4,63 @@ import { alt } from '../alt';
import GlobalNotificationActions from '../actions/global_notification_actions';
const GLOBAL_NOTIFICATION_COOLDOWN = 400;
class GlobalNotificationStore {
constructor() {
this.notificationQue = [];
this.notificationQueue = [];
this.notificationStatus = 'ready';
this.notificationsPaused = false;
this.bindActions(GlobalNotificationActions);
}
onAppendGlobalNotification(newNotification) {
let notificationDelay = 0;
for(let i = 0; i < this.notificationQue.length; i++) {
notificationDelay += this.notificationQue[i].dismissAfter;
}
this.notificationQueue.push(newNotification);
this.notificationQue.push(newNotification);
setTimeout(GlobalNotificationActions.emulateEmptyStore, notificationDelay + newNotification.dismissAfter);
if (!this.notificationsPaused && this.notificationStatus === 'ready') {
this.showNextNotification();
}
}
onEmulateEmptyStore() {
let actualNotificitionQue = this.notificationQue.slice();
showNextNotification() {
this.notificationStatus = 'show';
this.notificationQue = [];
setTimeout(GlobalNotificationActions.cooldownGlobalNotifications, this.notificationQueue[0].dismissAfter);
}
setTimeout(() => {
this.notificationQue = actualNotificitionQue.slice();
GlobalNotificationActions.shiftGlobalNotification();
}, 400);
onCooldownGlobalNotifications() {
// When still paused on cooldown, don't shift the queue so we can repeat the current notification.
if (!this.notificationsPaused) {
this.notificationStatus = 'cooldown';
// Leave some time between consecutive notifications
setTimeout(GlobalNotificationActions.shiftGlobalNotification, GLOBAL_NOTIFICATION_COOLDOWN);
} else {
this.notificationStatus = 'ready';
}
}
onShiftGlobalNotification() {
this.notificationQue.shift();
this.notificationQueue.shift();
if (!this.notificationsPaused && this.notificationQueue.length > 0) {
this.showNextNotification();
} else {
this.notificationStatus = 'ready';
}
}
onPauseGlobalNotifications() {
this.notificationsPaused = true;
}
onResumeGlobalNotifications() {
this.notificationsPaused = false;
if (this.notificationStatus === 'ready' && this.notificationQueue.length > 0) {
this.showNextNotification();
}
}
}