-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathindex.js
142 lines (140 loc) · 3.96 KB
/
index.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
'use strict';
import PUBNUB from 'pubnub';
const channel = 'PUBLISH_ACTIONS';
/**
* Wrapper to store actions and send them
*/
class PubActions {
constructor(pubnub) {
this.actions = [];
this.pubnub = pubnub;
}
add(action) {
this.actions.push({id: this.actions.length+1, action});
return this;
}
send() {
let message = JSON.stringify([this.actions[this.actions.length-1]]);
this.pubnub.publish({channel, message});
return this;
}
sendAll() {
let message = JSON.stringify(this.actions);
this.pubnub.publish({channel, message});
return this;
}
}
/**
* Middleware that publish it's new action to the receivers
* @returns {Function}
*/
const sendActionMiddleware = (pubnub) => {
const pubActions = new PubActions(pubnub);
// When a new member joined the channel -> publish all actions
pubnub.subscribe({ channel,
presence: (m)=>{
if (m.action === 'join') {
pubActions.sendAll();
}
},
message: ()=> {/* Do nothing*/ }
});
return store => {
return next => action => {
let result = next(action);
pubActions.add(action).sendAll();
return result;
};
};
};
/**
* Middleware that:
* 1. Block action from current user
* 2. Continue to next action only when it was recived from sender
* @returns {Function}
*/
const receiveActionMiddleware = (pubnub) => {
let mainStore,
curActionId = 0;
pubnub.subscribe({
channel,
message : message => {
message = JSON.parse(message);
if (Array.isArray(message)) {
message.map(actionObj => {
if (shouldAddAction(actionObj)) {
addAction(actionObj);
}
});
}
}
});
const shouldAddAction = message => message && message.id > curActionId;
const addAction = message => {
message.action.force = true;
mainStore.dispatch(message.action);
curActionId = message.id;
};
return store => {
mainStore = mainStore || store; // init main store
return next => action => {
if (!action.force) {
return action; // Block action change
} else {
return next(action);
}
};
};
};
/**
* Middleware that doesnt do anything (in case of regular user)
* @returns {Function}
*/
const farwardNextAction = () => {
return store => {
return next => action => {
let result = next(action);
return result;
};
};
};
/**
* Helper to extract query param from url
* @param field
* @param url
* @returns {null}
*/
const getQueryString = function (field) {
let href = window ? window.location.href : '',
reg = new RegExp('[?&]' + field + '=([^&#]*)', 'i'),
string = reg.exec(href);
return string ? string[1] : null;
};
/**
* Is this a sender user
* @returns {null}
*/
const isSender = (userType) => userType ? userType == 'sender' : getQueryString('sender');
/**
* Is this a receiver user
* @returns {null}
*/
const isReceiver = (userType) => userType ? userType == 'receiver' : getQueryString('receiver');
/**
* Return the middleware based on the url query param or userType:
* url?sender=true || userType='sender' -> will send actions to others
* url?receiver=true || userType='receiver'-> will block interaction and get actions from sender
* otherwise -> won't do anything
* @returns {Function}
*/
export default (publish_key, subscribe_key, userType) => {
let uuid = new Date().getTime();
const pubnub = PUBNUB.init({publish_key, subscribe_key, uuid});
if (isSender(userType)) {
return sendActionMiddleware(pubnub);
}
if (isReceiver(userType)) {
return receiveActionMiddleware(pubnub);
}
return farwardNextAction();
}