-
Notifications
You must be signed in to change notification settings - Fork 78
/
notifications.js
156 lines (143 loc) · 4.31 KB
/
notifications.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
import {treatNotification, preloadImage} from '../helpers';
import {DEFAULT_NOTIFICATION} from '../constants';
// An array to store notifications object
const INITIAL_STATE = [];
// Action types
const ADD_NOTIFICATION = 'ADD_NOTIFICATION';
const UPDATE_NOTIFICATION = 'UPDATE_NOTIFICATION';
const REMOVE_NOTIFICATION = 'REMOVE_NOTIFICATION';
const REMOVE_NOTIFICATIONS = 'REMOVE_NOTIFICATIONS';
/**
* Add a notification (thunk action creator)
*
* We use a thunk here to create an ADD_NOTIFICATION action
* and only return the notification object.
* @param {Object} notification
* @returns {Object} notification
*/
export const addNotification = (notification) => (dispatch) => {
if (!notification.id) {
notification.id = new Date().getTime();
}
notification = treatNotification(notification);
// if there is an image, we preload it
// and add notification when image is loaded
if (notification.image) {
preloadImage(notification.image, dispatch.bind(this, _addNotification(notification)));
}
else {
dispatch(_addNotification(notification));
}
return notification;
};
/**
* Add a notification (action creator)
*
* @param {Object} notification
* @returns {{type: string, payload: {Object}}}
* @private
*/
function _addNotification(notification) {
return {
type: ADD_NOTIFICATION,
payload: notification
};
}
/**
* Update a notification (thunk action creator)
*
* We use a thunk here to create an UPDATE_NOTIFICATION action
* and only return the notification object.
* @param {Object} notification
* @returns {Object} notification
*/
export const updateNotification = (notification) => (dispatch, getState) => {
if (!notification.id) {
throw new Error('A notification must have an `id` property to be updated');
}
const notifications = getState().notifications;
const index = notifications.findIndex((oldNotification) => oldNotification.id === notification.id);
const currNotification = notifications[index];
notification = treatNotification(notification);
// if image is different, then we preload it
// and update notification when image is loaded
if (notification.image && (!currNotification.image || (currNotification.image &&
notification.image !== currNotification.image))) {
preloadImage(notification.image, dispatch.bind(this, _updateNotification(notification)));
}
else {
dispatch(_updateNotification(notification));
}
return notification;
};
/**
* Update a notification (action creator)
*
* @param {Object} notification
* @returns {{type: string, payload: {Object}}}
* @private
*/
function _updateNotification(notification) {
return {
type: UPDATE_NOTIFICATION,
payload: notification
};
}
/**
* Remove a notification (action creator)
*
* @param {Object} notification
* @returns {{type: string, payload: {Object}}}
*/
export function removeNotification(notification) {
return {
type: REMOVE_NOTIFICATION,
payload: notification
};
}
/**
* Remove all notifications (action creator)
*
* @returns {{type: string}}
*/
export function removeNotifications() {
return {
type: REMOVE_NOTIFICATIONS
};
}
// Action creators
export const actions = {
addNotification: addNotification,
updateNotification: updateNotification,
removeNotification: removeNotification,
removeNotifications: removeNotifications
};
// Actions types
export const types = {
ADD_NOTIFICATION: ADD_NOTIFICATION,
UPDATE_NOTIFICATION: UPDATE_NOTIFICATION,
REMOVE_NOTIFICATION: REMOVE_NOTIFICATION,
REMOVE_NOTIFICATIONS: REMOVE_NOTIFICATIONS
};
// Reducers
export default (defaultNotification = DEFAULT_NOTIFICATION) => {
return (state = INITIAL_STATE, {type, payload}) => {
switch (type) {
case ADD_NOTIFICATION:
const notification = Object.assign({}, defaultNotification, payload);
return [...state, notification];
case UPDATE_NOTIFICATION:
// get index of the notification
const index = state.findIndex((notification) => notification.id === payload.id);
// replace the old notification by the new one
state[index] = Object.assign({}, defaultNotification, payload);
return [...state];
case REMOVE_NOTIFICATION:
return state.filter((notification) => notification.id !== payload);
case REMOVE_NOTIFICATIONS:
return [];
default:
return state;
}
};
};